所谓promise,简单来说是一个容器,里面保存着某个未来才会结束的事情(通常是一个异步操作)的结果,从语法上来讲Promise是一个对象,从它可以获取异步操作的消息。
Promise对象代表着一个异步操作,有三种状态,Pending(进行中),Fulfilled(已成功)和Rejected(已失败)。Promise对象的状态改变只能有两种可能:从Pending变为Fulfilled和从Pending变为Rejected。
基本用法
var promise = new Promise(function(resolve,regect){
//异步代码
if(异步操作成功){
resolev(异步操作结果);
}else{
reject(错误对象)
}
})
promise.then(function(value){},function(erroe){})
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数,由Javascript引擎提供,不用自己部署。
resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
reject函数的作用是将Promise对象的状态从“未完成”变为“失败”。在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。
##Promise.prototype.then
Promise实例生成之后,可以用then方法来分别指定resolve状态和reject状态的回调。then方法可以接受两个回调函数作为参数,第一个回调函数是Promise对象的状态变为Resolved时调用的,第二个回调函数是Promise对象变为Rejected时调用的,其中,第二个函数是可选的。不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
采用链式的then可以指定一组按照次序调用的回调函数,这样,前一个回调函数有可能返回地还是一个Promise对象,而后一个回调函数就会等待该Promise对象的状态发生改变后再被调用。
Promise.prototype.catch
Promise.prototype.catch方法是.then(null,reject)的别名,用于指定发生错误时的回调。
注意:Promise对象的错误具有冒泡的性质,会一直向后传递,直到被捕获为止,也就是说,错误总会被下一个catch语句捕获。一般来说,不要再then方法中定义Reject状态的回调函数,而应总是使用catch方法。
Promise.all
Promise.all方法用于将多个Promise实例包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3]);
p的状态由p1,p2,p3决定,分两种情况:
- 只有p1,p2,p3状态都变为Fulfiled,p的状态才会变为Fulfiled,此时,p1,p2,p3的返回值组成一个数组,传递给p的回调函数。
- 只要p1,p2,p3中有一个被Reject,p的状态就会变为Reject,此时,第一个被Reject的实例的返回值就会被传递给p的回调函数。
手动实现Promise.all
function promiseAll(promises) {
return new Promise(function (resolve,reject) {
//这个函数传入的参数首先必须要是一个数组,如果不是数组,则直接抛出异常
if(!promises instanceof Array){
throw new TypeError('Argument must be an Array');
}
//记录传入的promise对象的个数
let len = promises.length;
//记录状态为resolve的promise对象的个数
let resolvedCount = 0;
//保存一个promise对象的状态变为resolve之后的结果
let resolvedArray = new Array(len);
for(var i = 0;i<len;i++){
(function (i) {
//使用Promise.resolve方法将传递进来的参数转换成promise对象的实例
Promise.resolve(promises[i]).then(value => {
//如果这个promise对象的状态变为resolve,就给负责技术的变量加1
resolvedCount++;
//将这个异步操作的结果保存在刚开始设定的数组里
resolvedArray[i] = value;
//当所有的promise对象的状态都变为resolve的时候,这个最外面返回的promise对象的状态变为resolve,然后将保存之前的所有promise实例的结果的数组返回
if(resolvedCount === len){
return resolve(resolvedArray);
}
},rej=>{
//如果有一个实例的状态变成了reject,则直接将要返回的这个promise实例对象的状态变为reject并返回即可。
return reject(rej);
}).catch(reason=>{
console.log(reason);
})
})(i)
}
})
}
Promise.race
Promise.race方法用于将多个Promise实例包装成一个新的Promise实例。和Promise.all不同的是,只要多个Promise实例中的一个改变了状态,包装出来的这个新实例的状态就会跟着改变。那个率先改变的Promise实例的返回值就会传递给p的回调函数。本身并不会关注这个改变状态的promise的实例的状态是变成了resolved还是rejected。
手动实现Promise.race
//有了promise.all的实现思路,再实现race方法就简单很多了
function promiseRace(promises) {
return new Promise(function (resolve,reject) {
if(!promises instanceof array){
throw new TypeError('Argument must be an Array');
}
let length = promises.length;
for(var i = 0;i<length;i++){
(function (i) {
Promise.resolve(promises[i]).then(res=>{
return resolve(res)
},rej=>{
return reject(rej)
}).catch(reason => {
console.log(reason);
})
})(i)
}
})
}
Promise.resolve
Promise.resolve方法将现有的对象转为Promise对象。
Promise.resolve('foo')等价于:
new Promise(function(resolve){
resolve('foo');
})