Promise
对象是 JavaScript
的异步操做解决方案,为异步操做提供统一接口。它起到代理做用(proxy),充当异步操做与回调函数之间的中介,使得异步操做具有同步操做的接口。javascript
Promise
可让异步操做写起来,就像在写同步操做的流程,而没必要一层层地嵌套回调函数。java
若是几个异步操做之间并无先后顺序之分,但须要等多个异步操做都完成后才能执行后续的任务,没法实现并行节约时间。数组
在 ES6 Promises
标准中定义的API还不是不少,目前大体有下面三种类型。promise
首先,Promise
是一个对象,也是一个构造函数。bash
function f1(resolve, reject) {
// 异步代码...
}
var promise = new Promise(f1);
复制代码
Promise
对象经过自身的状态,来控制异步操做。Promise实例具备三种状态。异步
这三种的状态的变化途径只有两种。函数
因此Promise
的最终结果只有两个,ui
fulfilled
。rejected
。promise.then(onFulfilled, onRejected)
// resolve(成功)时,onFulfilled 会被调用
// reject(失败)时,onRejected 会被调用
复制代码
像 Promise
这样的全局对象还拥有一些静态方法。包括 Promise.all()
还有Promise.resolve()
等在内,主要都是一些对Promise
进行操做的辅助方法。this
Promise
的实现resolve
和reject
都是函数spa
//构造函数中
function Promise(executor) {
let self = this;
/*初始化status*/
self.status = 'pending';
/*初始化value*/
self.value = undefined;
/*订阅事件的数组*/
self.onResolvedCallBacks = [];
self.onRejectedCallBacks = [];
/*此函数将Promise实例的状态由pending 转化为 fulfilled*/
function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
setTimeout(function () {
if (self.status === 'pending') {
self.status = 'fulfilled';
self.value = value;
/*发布已经订阅过的事件*/
self.onResolvedCallBacks.forEach(item => item(self.value))
}
}, 0)
}
/*此函数将Promise实例的状态由pending 转化为 rejected*/
function reject(reason) {
setTimeout(function () {
if (self.status === 'pending') {
self.status = 'rejected';
self.value = reason;
/*发布已经订阅过的事件*/
self.onRejectedCallBacks.forEach(item => item(self.value))
}
}, 0)
}
// new Promise 的时候,执行器(executor)的代码会当即执行
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
复制代码
promise
成功后,onFullfilled
会被调用。而且把promise
的值当作它的第一个参数。promise
在成功以前,不会调用它,而且只能被调用一次。reject
也同样。调用 then
方法后,返回一个全新的 promise
。
// 先封装一个方法
function resolvePromise(promise2,x,resolve,reject){
//
if(promise2 === x){
return reject(new TypeError('循环引用'));
}
// 为了防止 resolve 和 reject 同时调用
let called = false;//promise2是否已经resolve 或reject了,防止重复调用
if(x instanceof Promise){
if(x.status == PENDING){
x.then(function(y){
resolvePromise(promise2,y,resolve,reject);
},reject);
}else{
x.then(resolve,reject);
}
//x是一个thenable对象或函数,只要有then方法的对象,
}else if(x!= null &&((typeof x=='object')||(typeof x == 'function'))){
//当咱们的promise和别的promise进行交互,编写这段代码的时候尽可能的考虑兼容性,
//容许别人瞎写,x能够是对象,也能够是函数
try{
let then = x.then;
if(typeof then == 'function'){
//有些promise会同时执行成功和失败的回调
then.call(x,function(y){
//若是promise2已经成功或失败了,则不会再处理了
if(called)return;
called = true;
resolvePromise(promise2,y,resolve,reject)
},function(err){
if(called)return;
called = true;
reject(err);
});
}else{
//到此的话x不是一个thenable对象,那直接把它当成值resolve promise2就能够了
// 当返回一个对象 {name:'a',then:{age:8}},对象里的then不是thenable对象
resolve(x);
}
}catch(e){
if(called)return;
called = true;
reject(e);
}
}else{
//若是X是一个普通 的值,则用x的值去resolve promise2
resolve(x);
}
}
Promise.prototype.then = function(onFulfilled,onRejected){
//若是成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值日后抛,叫作值的穿透
// 例如:promise.then().then().then(function(data){},function(err){})
onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function(value){return value};
onRejected = typeof onRejected == 'function'?onRejected:reason=>{throw reason};
//若是当前promise状态已是成功态了,onFulfilled直接取值
let self = this;
let promise2;
if(self.status == FULFILLED){
return promise2 = new Promise(function(resolve,reject){
setTimeout(function(){
try{
let x =onFulfilled(self.value);
//若是获取到了返回值x,会走解析promise的过程
resolvePromise(promise2,x,resolve,reject);
}catch(e){
//若是执行成功的回调过程当中出错了,用错误缘由把promise2 reject
reject(e);
}
})
});
}
if(self.status == REJECTED){
return promise2 = new Promise(function(resolve,reject){
setTimeout(function(){
try{
let x =onRejected(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
})
});
}
if(self.status == PENDING){
return promise2 = new Promise(function(resolve,reject){
self.onResolvedCallbacks.push(function(){
try{
let x =onFulfilled(self.value);
//若是获取到了返回值x,会走解析promise的过程
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
});
self.onRejectedCallbacks.push(function(){
try{
let x =onRejected(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
});
});
}
}
复制代码
Promise.prototype.catch=function (callback) {
return this.then(null,callback);
}
---------使用-------
let promise = new Promise(function (resolve, reject) {
reject('错误');
})
promise.then(function(data){console.log(data)}).catch(e=>{console.log(e)});
复制代码
Promise.all = function (promises) {
return new Promise(function (resolve,reject) {
let arr =[];//arr是最终返回值的结果的集合。
let j =0;
function processData(i,data){// 每调用一次此函数,j就会+1;
arr[i] = data;// 每次成功的结果都放入数组中
if(++j===promises.length){
resolve(arr); //只有promises中的最后一个成功,才能调用resolve方法。
}
}
for(let i=0;i<promises.length;i++){
promises[i].then(function (data) {
processData(i,data);
},reject)// 若是有一个失败,总体就会失败
}
})
}
复制代码
使用方法:
function read(file) {
return new Promise1(function (resolve, reject) {
require('fs').readFile(file,'utf8',function (err, data) {
resolve(data);
})
})
}
Promise1.all([read('./1.txt'),read('./2.txt')]).then(function (data) {
console.log(data)
})
// ['file1','file2']
复制代码
只要有一个promise成功,就会执行成功的回调,参数是由 promise 组成的数组
Promise.race=function (promises) {
return new Promise(function (resolve, reject) {
for(let i=0;i<promises.length;i++){
promises[i].then(resolve,reject);
}
})
}
复制代码
Promise.resolve = function (value) {
return new Promise(function (resolve, reject) {
resolve(value)
})
}
复制代码
Promise.reject = function (reason) {
return new Promise(function (resolve, reject) {
reject(reason);
})
}
复制代码
Promise
对象的缺点:一、没法取消Promise
,一旦新建它就会当即执行,没法中途取消。
二、若是不设置回调函数,Promise
内部抛出的错误,不会反应到外部。
三、当处于Pending
状态时,没法得知目前进展到哪个阶段(刚刚开始仍是即将完成)。