什么是Promise?
MDN文档对Promise的解释是: Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
民间也有一种说法是: Promise是优雅解决异步回调函数嵌套地狱问题的一种解决方案。
下面是我个人对Promise的一个通俗的解释:
什么是Promise/A+? 它跟ECMAScript 6的Promise又是什么关系?
- Promise/A+是Promise的一个开放的标准或者是规范,它规范了Promise的术语和要求(包括Promise的三种状态、必须提供一个then方法和Promise的解决流程)。
- ECMAScript 6里面的Promise是Promise/A+规范的一种实现方案。它是一个规范的具体的一种实现方案,它在原有的Promise/A+规定上扩展了一些API:
Promise.prototype.catch()
Promise.prototype.finally()
Promise.allSettled()
Promise.all()
Promise.race()
Promise.any()
Promise.reject()
Promise.resolve()
下面是用图来形容它们之间的关系
来看看Promise流程图:
下面是一个实现了Promsoe/A+规范同时也扩展了ECMAScript6的PromiseAPI的源码并且含有大量注释。(通过了所有promises-aplus-test的测试案例)
如果你也想测试你自己编写的Promsie是否符合**Promise/A+**规范可以下载一个 “promises-aplus-test” 的工具来测试。下面是安装命令:
npm install promises-aplus-tests -g
下面是promises-aplus-test的用法:
Promise.deferred = function() {
const deferred = {
}
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve
deferred.reject = reject
})
return deferred
}
module.exports = Promise;
在你编写的promise文件的末尾添加这些代码然后在命令行运行下面命令就可以
promises-aplus-tests 你要测试的文件名.js
下面是我编写的Promise源码
const PEDDING = "pending",
FULFILLED = "fulfilled",
REJECTED = "rejected";
function isPromise(val) {
return (
val !== undefined &&
val !== null &&
(typeof val === 'object' || typeof val === 'function') &&
typeof val.then === 'function'
);
}
/**
* @todo The Promise Resolution Procedure=>Promise的解决流程
* @description Promise/A+ 规范
* 的承诺解决过程是一个抽象的操作作为输入一个承诺和一个值,它表示我们作为[[Resolve]](promise, x)。如果x是可能的,则在行为至少类似于承诺的假设下,
* 尝试promise采用的状态。否则,它将满足value 。xxpromisex只要对约定的实现公开Promises / A +兼容的then方法,对约定的实现就可以进行互操作。
* 它还允许Promises / A +实现以合理的then方法“同化”不合格的实现。
要运行[[Resolve]](promise, x),请执行以下步骤:
2.3.1 如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
2.3.2 如果x是一个承诺,则采用其状态[ 3.4 ]:
2.3.2.1 如果x未决,则promise必须保持未决状态,直到x实现或被拒绝。
2.3.2.2 如果/何时x满足,promise则以相同的值满足。
2.3.2.3 如果/何时x被拒绝,promise则以相同的理由拒绝。
2.3.3 否则,如果x是对象或函数,
2.3.3.1 我们then是x.then。[ 3.5 ]
2.3.3.2 如果检索属性x.then中抛出的异常的结果e,拒绝promise与e作为的原因。
2.3.3.3 如果then是函数,请使用xas this,第一个参数resolvePromise和第二个参数进行调用rejectPromise,其中:
2.3.3.3.1 如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
2.3.3.3.2 如果/当rejectPromise是带一个理由r,拒绝promise与r。
2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,而所有其他调用均被忽略。
2.3.3.3.4 如果调用then引发异常e,
2.3.3..3.4.1 如果resolvePromise或rejectPromise已经被调用,则忽略它。
2.3.3..3.4.2 否则,拒绝promise与e作为的原因。
2.3.3.4 如果then不是一个函数,实现promise用x。
2.3.4 如果x不是一个对象或功能,实现promise与x。
如果使用参与循环的可循环链的可转换组件来解决承诺,从而[[Resolve]](promise, thenable)最终导致递归性质[[Resolve]](promise, thenable)被再次调用,
则遵循上述算法将导致无限递归。鼓励但不是必需的实现,以检测这种递归并promise以提供信息TypeError为理由的拒绝。[ 3.6 ]
* @param {Promise} promise2
* @param {*} x
* @param {Function} resolve
* @param {Function} reject
* @returns {void}
*/
function resolvePromise(promise2, x, resolve, reject) {
//如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
/**
* 例子:
* const p=new Promise((resolve,reject)=>{
* resolve(xxx);
* }).then(v=>{
* return p;
* })
*/
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
//保证promise2的onFulfilled或者onRejected只被调用一次 防止多次调用
//比如:
/**
* new Promise((resolve,reject)=>{
* resolve(xxx);
* reject(xxx);
* resolve(xxx);
* });
* 这样就会导致promise2的onFulfilled或者onRejected被多次调用
*/
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
//then be x.then=>取出then
const then = x.then;
// 如果then是函数,就默认是promise了
if (typeof then === 'function') {
then.call(x,
//If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).=> 如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
(y) => {
//只能调用一次
if (called) return;
called = true;
//如果y依旧是一个promise 那么就递归解析
/**
* 例子:
* new Promose((resolve,reject)=>{
* resolve('xxx');
* }).then((v)=>{
* return new Promise((resolve,reject)=>{
* setTimeout(()=>{
* resolve(new Promise((resolve,reject)=>{
* resolve(new Promise((resolve,reject)=>{
* resolve(new Promise(...);//嵌套地狱
* }))
* }))
* }13000)
* })
* })
*/
resolvePromise(promise2, y, resolve, reject);
},
//If/when rejectPromise is called with a reason r, reject promise with r.=> 如果/当rejectPromise是带一个理由r,拒绝promise与r。
(r) => {
//只能调用一次
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
//取then失败或者流程报错走到这里
if (called) return;
called = true;
reject(e);
}
} else {
//If x is not an object or function, fulfill promise with x.=>如果x不是一个对象或者函数
resolve(x);
}
}
class Promise {
/**
* @description Promise 构造器主要用于包装不支持promise(返回值不是Promise)的函数。
* @param {*} executor
*/
constructor(executor) {
if (isPromise