咱们在作项目的时候常常遇到多个回调函数嵌套在一块儿的状况,一层套一层,代码不够直观而且不容易维护,就是所谓的回调地狱。Promise 就很好的解决了这个问题。npm
若是几个异步操做之间并无先后顺序之分,但须要等多个异步操做都完成后才能执行后续的任务,没法实现并行节约时间。数组
Promise是抽象异步处理对象以及对其进行各类操做的组件。在 ES6 Promises 标准中定义的API还不是不少。目前大体有下面三种类型。promise
//要想建立一个promise对象、可使用new来调用Promise的构造器来进行实例化。
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
复制代码
// 对经过new生成的promise对象为了设置其值在成功/失败时调用的回调函数 可使用promise.then() 实例方法。
// resolve(成功)时onFulfilled 会被调用
// reject(失败)时onRejected 会被调用
promise.then(onFulfilled, onRejected)
复制代码
// 一些对Promise进行操做的辅助方法,包括 Promise.all() 、Promise.race() 、Promise.resolve()、Promise.reject() 等
复制代码
无论两个promise谁先完成,Promise.all 方法会按照数组里面的顺序将结果返回异步
Promise.race([p1, p2]).then(function (result) {
console.log(result); // [ '2.txt', '2' ]
});
复制代码
以前接触过Promise,可是对Promise的调用和状态变化一直很模糊,死记硬背后过了一段时间就忘记了,很痛苦,一直想要从根本上弄懂Promise。最近直接根据Promise/A+规范,本身实现了一个简单版本的Promise库。废话很少说,上干货。函数
// Promise 有三种状态(pending, fulfilled, rejected),初始值为pending。
// Promise 有两个执行函数来改变状态的值,成功的时候执行resolve,失败的时候执行reject。
复制代码
//构造函数中
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);
}
}
复制代码
每次调用then方法后都会返回一个新的Promise实例测试
Promise.prototype.then = function (onFulfilled, onRejected) {
/*当没有函数传递进来的时候,添加默认函数*/
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
return value
};
onRejected = typeof onRejected === 'function' ? onRejected : function (err) {
throw err
};
let self = this;
/*因为要实现链式调用,因此每次执行then方法的时候都会返回一个新的Promise实例*/
let promise2;
if (self.status === 'fulfilled') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
/*将onFulfilled函数执行的结果resolve掉*/
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
})
}
if (self.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
/*将onRejected函数执行的结果reject掉*/
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
})
}
if (self.status === 'pending') {
promise2 = new Promise(function (resolve, reject) {
/*订阅事件*/
self.onResolvedCallBacks.push(function () {
try {
let x = onFulfilled(self.value);
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);
}
});
})
}
return promise2;
};
/*辅助函数 --> 解决多层嵌套状况*/
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'))
}
let then, called;
if (x != null && (typeof x === 'function' || typeof x === 'object')) {
try {
then = x.then;
if (typeof then === 'function') {
then.call(x, function (data) {
if (called) return;
called = true;
resolvePromise(promise2, data, resolve, reject)
}, function (err) {
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
复制代码
<!--其实就是then的变形-->
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
/* 测试Promise/A+规范的方法 npm i -g promises-aplus-tests promises-aplus-tests Promise.js */
复制代码
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let count = 0;
let result = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (data) {
result[i] = data;
if (++count === promises.length) {
resolve(result);
}
}, function (err) {
reject(err);
});
}
})
};
复制代码
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的功能。给我最直接的感受就是,看似难懂的东西只要弄懂了后面是怎么实现的,用法就很简单了。固然在弄懂源码逻辑道路确实不容易,可是一遍不行两遍,两遍不行三遍。。。依次次类推,每次都有不一样的收获,我想这就是传说中的‘读书百遍,其义自见’吧。ui