Promise小结
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) 、Resolved(已经完成)和Rejected(已失败)
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
1
2
3
4
5
6
7
|
var promise= new Promise( function (resove,reject){ if ( /* 异步操作成功 */ ){ resolve(value); } else { reject(error); } }) |
Promise实例生成以后,可以用then
方法分别指定Resolved
状态和Reject
状态的回调函数。
1
2
3
4
5
|
promise.then( function (value) { // success }, function (error) { // failure }); |
案例
1
2
3
4
5
6
7
|
var promise= new Promise( function (resolve,reject){ console.log( 'promise' ); }) promise.then( function (){ console.log( '我后执行' ) }) console.log( '我先执行' )<br><br> //上面代码中,Promise新建后立即执行,所以首先输出的是“Promise”。然后,<code>then</code>方法指定的回调函数,<br>//将在当前脚本所有同步任务执行完才会执行,所以“我后执行” 最后输出。 |
ajax
var
http = {
get:
function
(url) {
var
promise =
new
Promise(
function
(resolve, reject) {
$.ajax({
url: url,
method:
'get'
,
success:
function
(data) {
resolve(data);
},
error:
function
(xhr, statusText) {
reject(statusText);
}
});
});
return
promise;
}
};
http.get(
'solve.php'
).then(
function
(data) {
return
data;
},
function
(err) {
return
Promise.reject(
'Sorry, file not Found.'
);
}).then(
function
(data) {
document.write(data);
},
function
(err) {
document.write(err);
});

1 var getJSON=function(url){
2 var promise=new Promise(function(resolve,reject){
3 var xhr=new XMLHttpRequest();
4 xhr.open('get',url);
5 xhr.onreadystatechange=handler;
6 xhr.send(null);
7
8 function handler(){
9 if(this.readystate!==4){
10 return;
11 }
12 if(this.status==200){
13 resolve(this.responseText)
14 }else{
15 reject(new Error(this.statusText));
16 }
17 }
18 })
19 return promise;
20 }
21 getJSON("/get.json").then(function(json) {
22 console.log('Contents: ' + json);
23 }, function(error) {
24 console.error('出错了', error);
25 });

Promise三种状态
pending、resolved、rejected
使用语法
var promis = new Promise(function(resolve,reject){
$.ajax({
url:'/api/something.json',
method:'get',
datatype:'json',
success:(res) =>{
resolve(res)
},
error:(err)=>{
reject(err)
}
})
})
promis.then(function(res){
console.log(res)
}).catch(function(err){
console.log(err)
});
Promise.prototype.then()
链式调用,状态变为resolve
如果把下一步想要的东西return出去,即可让下一个then使用
var promise = new Promise(function(resolve,reject){
$.ajax({
url:'/api/poisearch.json',
method:'get',
datatype:'json',
success:(res) =>{
resolve(res)
},
error:(err)=>{
reject(err)
}
})
})
promise.then(function(res){
return res.data
}).then(function(data){
return data.result;
}).then(function(result){
console.log(result)
});
上面的代码还可以借用箭头函数简写成,极大提升了代码的简洁性和可读性
promise.then(res => res.data)
.then(data => data.result)
.then(result => console.log(result));
Promise.prototype.catch()
如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。
- 另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
- 如果Promise状态已经变成Resolved,再抛出错误是无效的。
- catch方法返回的还是一个Promise对象,因此后面还可以接着调用then方法。
Promise.all()
多个Promise实例,包装成1个,有点类似Array.prototype.every()
用法:
var p = Promise.all([p1, p2, p3]);
- 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
- 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
Promise.race()
多个Promise实例,包装成1个,有点类似Array.prototype.some()
- p1、p2、p3其中一个状态变成fulfilled,p的状态就会变成fulfilled
- 那个率先改变的Promise实例的返回值,就传递给p的回调函数。
done()、finally()
新的ES6中引入了promise的概念,目的是让回调更为优雅。层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用。于是Promise就应运而生。Promise即承诺的意思,new一个Promise就是新建一个承诺。在新建一个承诺的时候你需要做两件事情:
1.指定承诺所需完成的事
2.设置承诺是否实现的标准
下面我们来定义一个承诺:
1.承诺的内容:“获取data.php的数据”,
2.承诺是否实现的评判是:“是否获取data.php的数据 ”
这里我们会用到jQuery.ajax()方法,这会让我们的代码显得简单精炼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var http = { get: function (url) { var promise = new Promise( function (resolve, reject) { $.ajax({ url: url, method: 'get' , success: function (data) { resolve(data); }, error: function (xhr, statusText) { reject(statusText); } }); }); return promise; } }; http.get( 'data.php' ).then( function (data) { document.write(data); }, function (err) { document.write(err); }); |
这里是获取的data值
1
2
3
|
/* data.php文件 */ <?php echo '{"name":"Tom","age":"22"}' ; |
在http请求中,我们定义了一个get方法,在get方法中,我们定义了一个promise的对象,而不是直接直接使用ajax获取到我们想要的数据,在这个get方法,我们最后得到的是一个promise对象,对于这种需要等待的操作,我们采用promise去处理,返回给主线程的是一个promise对象,而不是一个最终的数据,这是延迟程序给主程序的一个承诺,主线程可以根据通过返回的promise对象获取数据或者处理错误。这使得异步处理变得优雅而简单。
在jQuery.ajax()中,我们采用了两个方法来判断是否实现了我们的承诺,它们分别是resove和reject方法,如果如果jQuery.ajax()执行了success,并且返回的data中有数据,那么我们就判定这个承诺已经实现了(fulfilled),则调用resolve方法。如果jQuery.ajax()执行了error,那么我们就判定这个承诺被拒绝了(rejected),则调用reject方法。
那resove和reject这两个方法分别执行了哪些操作呢?这个我们就需要从Promise这个构造函数本身的结构说起。Promise这个构造函数结构大概是下面这样的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/* 用于描述思维的代码 */ function Promise(executor) { // 共有三种状态:pending(准备)、fulfilled(完成)、rejected(拒绝) this .PromiseStatus = 'pending' ; // 用于存储返回的数据 this .PromiseValue; // 完成 var resolve = function (reson) {}; // 拒绝 var reject = function (reson) {}; ... // 开始执行承诺 executor(resolve, reject); } Promise.prototype.then = function () {}; Promise.prototype.chain = function () {}; Promise.prototype. catch = function () {}; ... |
PromiseStatus:用于记录Promise对象的三种状态,这三中状态分别是:
pending:待定状态,Promise对象刚被初始化的状态
fulfilled:完成状态,承诺被完成了的状态
rejected:拒绝状态,承诺完成失败的状态
Promise的初始状态是pending。随后会更具承诺完成的情况更改PromiseStatus的值。
PromiseStatus:用于记录返回的数据或者错误。当承诺完成时,会把返回的数据赋给PromiseStatus。如果承诺执行失败了,那么失败的原因也会赋给此变量。
resolve()和reject():Promise构造函数中有两个闭包的函数resolve()和reject()。在new一个新的Promise的时候会传递一件你需要做的事情(executor)。这个executor是一个函数,在Promise的构造函数中它会被传入两个参数,这两个参数即我们的两个闭包的函数resolve()和reject(),以便你在executor中判定是否完成了你的承诺。
executor(): executor()函数中执行的代码就是子程序需要完成事。在executor()函数内如果调用了resolve(),resolve()则会把Promise对象的状态PromiseStatus修改为fulfilled,把resolve(value)中的value值赋给Promise对象的PromiseValue。然后再依次执行由then()方法构成的回调链中的回调函数。同样,在executor()中调用reject()的过程也是类似的。调用过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/* 用于描述思维的代码 */ executor(resolve, reject) { ... resolve(value); ... } ... resolve(value) { PromiseStatus = 'fulfilled' ; PromiseValue = value; ... // 接着调用回调链中的回调函数 } |
then(onFulfilled, onRejected):这个方法实际上是把onFulfilled()函数和onRejected()函数添加到Promise对象的回调链中。回调链就像一个由函数组构成的队列,每一组函数都是由至少一个函数构成(onFulfilled() 或者 onRejected() 或者 onFulfilled() 和 onRejected())。当resolve()或者reject()方法执行的时候,回调链中的回调函数会根据PromiseStatus的状态情况而被依次调用。
onFulfilled(value)和onRejected(reason):参数value和reason的实参都是PromiseValue。这里有一点值得注意,如果onFulfilled(value)和onRejected(reason)这两个回调函数中return返回值不是一个Promise的对象,那么这个返回值会被赋给PromiseValue,并在下一个then()的onFulfilled(value)和onRejected(reason)中做为实参使用。但如果这个返回值是一个Promise的对象,那么剩下的由then()构造的回调链会转交给新的Promise对象并完成调用。
有这样一个问题,如果在第一个then()中执行了onRejected(reason)回调函数,并且没有return任何值的时候,那么下一个then()中将会调用onFulfilled(value)方法,而不是onRejected(reason)。因为在执行上一个then()的onRejected(reason)回调函数的时候并没有出现错误或异常,所以PromiseStatus的状态就被更改为fulfilled了。为了避免这个问题,我们可以在onRejected(reson)中返回一个Promise对象并reject()。代码如下,我们要去访问一个并不存在的文件solve.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
var http = { get: function (url) { var promise = new Promise( function (resolve, reject) { $.ajax({ url: url, method: 'get' , success: function (data) { resolve(data); }, error: function (xhr, statusText) { reject(statusText); } }); }); return promise; } }; http.get( 'solve.php' ).then( function (data) { return data; }, function (err) { return Promise.reject( 'Sorry, file not Found.' ); }).then( function (data) { document.write(data); }, function (err) { document.write(err); }); |
Promise.reject()方法会返回一个被reject()的Promise对象,因此使得我们可以继续走下一个then()中的onRejected(reason)方法。
Promise小结的更多相关文章
- 从netty-example分析Netty组件续
上文我们从netty-example的Discard服务器端示例分析了netty的组件,今天我们从另一个简单的示例Echo客户端分析一下上个示例中没有出现的netty组件. 1. 服务端的连接处理,读 ...
- promise知识点小结
断断续续学习es6也有一段时间了,趁着开学空闲对知识点做一些小结. 为什么使用promise 谈到Promise,我们知道,这是社区较理想的异步编程解决方案.想要掌握promise,我们首先要知道其提 ...
- 深入理解jQuery、Angular、node中的Promise
最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供 ...
- 细嗅Promise
读完这篇文章,预计会消耗你 40 分钟的时间. Ajax 出现的时候,刮来了一阵异步之风,现在 Nodejs 火爆,又一阵异步狂风刮了过来.需求是越来越苛刻,用户对性能的要求也是越来越高,随之而来的是 ...
- gulp使用小结(二)
接上篇文章接Gulp使用小结(一) 内容如下: 首先,偶在gulp-demos上已经提交了个较通用的栗子...俺琢磨半天,原准备分阶段搞些 Gulp 套路,但是写完介个栗子之后,觉得已经能覆盖绝大多数 ...
- Promise与Defer认识
1.deffer对象:jquery的回掉函数解决方案:含义是延迟到未来某个点再执行: 2.$.ajax链式写法: $.ajax("test.php") .done(func ...
- JQ中的延迟对象deferred中的promise等的使用
一.什么是deferred对象? 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们 ...
- 延期(deferred)的承诺(promise) — jq异步编程浅析
引子 相信各位developers对js中的异步概念不会陌生,异步操作后的逻辑由回调函数来执行,回调函数(callback function)顾名思义就是“回头调用的函数”,函数体事先已定义好,在未来 ...
- Paxos算法小结
转自不正直的绅士,因百度空间迁移,无法注明出处,我从其google搜索引擎中的cache进行的copy. 不正直的绅士 是跟我一起工作过的非常有才的一个青年才俊. Paxos的使用非常广泛.sanlo ...
随机推荐
- Redis 主从部署
Redis 主从部署 http://www.xuchanggang.cn/archives/978.html
- MAC Pro 2017款 无线上网慢
MAC Pro 2017款 在无线路由器和MAC相隔一个房间,上网很慢,怀疑是无线路由器有问题,但其他几台老款MAC和PC上网正常.后来将蓝牙关掉,上网就很快了.
- POJ-2398
Toy Storage Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4243 Accepted: 2517 Descr ...
- 用淘宝镜像cnpm代替npm
安装淘宝镜像cnpm: $ sudo npm install -g cnpm --registry=https://registry.npm.taobao.org 然后就大部分可以用cnpm来代替np ...
- Django2.x版本路由系统的正则写法以及视图函数的返回问题
一.关于url.py urlpatterns每个元素的不再用url(),而是path(),最重要的一点是,正则的使用需要你自己手动导入re_path,并且在每个使用正则匹配的的元素用re_path() ...
- 【面试题】2018年最全Java面试通关秘籍汇总集!
[面试题]2018年最全Java面试通关秘籍汇总集!(转载于互联网) 前几天在交流群里有些小伙伴问面试相关的试题,当时给出了一些问题,苦于打字太累就没写下去了,但觉得这是一个很不负责任的表现,于是 ...
- asp.net mvc 中使用NPOI导出excel
版本信息:NPOI1.2.5(2.0以上的版本很多方法不清楚) 明确三点: path: mvc 部署网站的时候,我们肯定要拷贝的一个文件夹就mvc的UI层,有点可以肯定的是,你部署网站的路径不一定都是 ...
- Linux命令之head
head [选项] [文件] head命令输出文件开头部分,默认情况下显示文件的头10行.如果指定多个文件,每个文件前都有一个标题,给出文件名.如果没有指定文件,或当文件为-时,读取标准输入. (1) ...
- 【Go】基础语法之接口
接口定义: 利用关键字interface来定义一个接口,接口是一组方法的集合. 例如: type People interface { Show(name string, age int) (id i ...
- Linux基础系列-系统密码破解
无引导介质(光盘.iso)救援模式下root密码破解 第一步: GRUB启动画面读秒时按上下方向键,进入GRUB界面 第二步: 使用上下光标键选择要修改的操作系统启动内核(默认选择的即可),按e键进行 ...