Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,赞成了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) 、Resolved(已经完成)和Rejected(已失败)javascript
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。php
1
2
3
4
5
6
7
|
var
promise=
new
Promise(
function
(resove,reject){
if
(
/* 异步操做成功 */
){
resolve(value);
}
else
{
reject(error);
}
})
|
Promise实例生成之后,能够用then
方法分别指定Resolved
状态和Reject
状态的回调函数。java
1
2
3
4
5
|
promise.then(
function
(value) {
// success
},
function
(error) {
// failure
});
|
案例es6
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>//将在当前脚本全部同步任务执行完才会执行,因此“我后执行” 最后输出。
|
ajaxajax
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 });
pending、resolved、rejectedjson
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) });
链式调用,状态变为resolve
若是把下一步想要的东西return出去,便可让下一个then使用api
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));
若是异步操做抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。promise
多个Promise实例,包装成1个,有点相似Array.prototype.every()
用法:闭包
var p = Promise.all([p1, p2, p3]);
多个Promise实例,包装成1个,有点相似Array.prototype.some()
新的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)方法。