文章内容输出来源:拉勾教育 大前端高薪训练营
前言
在ES6中,新增加了一种异步编程的解决方案Promise,它是一种规范,是一套处理JavaScript异步的机制。
Promise的含义
简单来说,它是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,通过它可以获取异步操作的消息。
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。
Promise 对象有两个特点:
1、对象的状态不受外界影响。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:
* 从 pending 变为 fulfilled;
* 从 pending 变为 rejected。
Promise的基础用法
Promise是一个类,它的构造函数中需要一个执行器作为参数传入进去,当使用Promise创建promise实例时,执行器会立即执行。在执行器中需要两个函数作为参数传递,即 resolve 和 reject 函数,这两个函数主要是用来更改状态的。
resolve 函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject 函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- 类核心逻辑的实现
下面我们来模拟一下Promise的类核心逻辑的实现。
代码如下(示例):(promise.js)
// 定义Promise构造函数
// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {
// 传入执行器, 创建实例时,立即执行
constructor (executor) {
executor(this.resolve, this.reject);
}
status = PENDING; // 初始化状态 为 pending 等待
value = undefined; // 保存成功之后的值
reason = undefined; // 保存失败后的原因
resolve = value => {
// 如果状态不是等待,阻止程序向下执行
if (this.status !== PENDING) return
// 将状态更改为成功 pending --> fulfilled
this.status = FULFILLED
// 保存成功之后的值, 传入的值
this.value = value
}
reject = reason => {
// 如果状态不是等待,阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败 pending --> rejected
this.status = REJECTED;
// 保存失败后的原因,传入的原因
this.reason = reason;
}
}
module.exports = Promise;
创建实例 代码如下(示例):(index.js)
// 引入 promise 模块
const Promise = require('./promise')
// 创建 Promise实例,返回 promise对象
let promise = new Promise((resolve, reject) => {
resolve(111);
})
console.log(promise);
/*
Promise:{
status: 'fulilled',
value: 111,
reason: undefined,
resolve: [Function: resolve],
reject: [Function: reject]
}
*/
在上面的代码中,我们已经通过代码创建了 Promise构造函数,并通过调用构造函数创建了 promise实例,且返回了一个 promise对象。那么,实例创建成功以后,我们如何指定resolved状态和rejected状态的回调函数呢?
Promise.prototype.then()
在 Promise的原型对象中定义了一个then方法,then方法主要做的事情就是判断状态,如果状态是成功的,那么调用成功的回调函数;如果状态是失败的,那么调用失败的回调函数。而要调用then方法,必须返回一个 promise对象,在上面的代码中,我们已经实现了返回 promise对象。 then方法有两个参数:一个是成功回调函数,它接收一个参数,表示成功之后的值;二是失败回调函数,它也接收一个参数,表示失败后的原因。
下面让我们来看一下 then方法 的基础实现过程。
代码如下(示例):(promise.js)
// 重复代码以下使用 ...... 代替
......
class Promise {
......
then (successCallback, failCallback) {
if (this.status === FULFILLED) {
// 成功回调函数,将传入resolve函数中传入的值进行传入
successCallback(this.value)
} else if (this.status === REJECTED) {
// 失败回调函数,将传入reject函数中传入的原因进行传入
failCallback(this.reason)
}
}
}
调用then方法 代码如下(示例):(index.js)
let promise = new Promise((resolve, reject) => {
resolve(111);
})
promise.then(value => console.log(value), reason => console.log(reason))
// 打印:1111
在上面的代码中,由于我们在创建实例时,抛出的是成功的函数resolve,所以此时,then方法中执行的是成功的回调函数,此时value的值为resolve中保存的值,即value = 111,所以打印出111。
自此,我们已经完成了基本的 Promise的类核心逻辑。但是我们只是进行了同步的操作,并没有引入异步的逻辑,而在前面我们也讲到Promise主要就是为了解决异步操作的。
那么,我们接下来看一下,Promise是如何处理异步操作的?
代码如下(示例):(promise.js)
......
class Promise {
......
// 成功回调
successCallback = undefined
// 失败回调
failCallback = undefined
resolve = value => {
......
// 此时是只调用一次then方法的写法
// 判断成功回调是否存在 如果存在 调用
this.successCallback && this.successCallback(this.value)
}
reject = reason => {
......
// 此时是只调用一次then方法的写法
// 判断失败回调是否存在 如果存在 调用
this.failCallback && this.failCallback(this.reason);
}
then (successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else { // 等待期
// 处理异步操作
/* 添加定时器(异步操作),导致 promise的状态进入等待期。
1、如果我们不将成功回调和失败回调存储起来,那么定时器中的resolve(100)或者reject('error'),将不会被执行;
2、需要在resolve和reject函数中判断成功回调和失败回调是否存在,存在时才会被调用
*/
// 此时是只调用一次then方法的写法
this.successCallback = successCallback;
this.failCallback = failCallback;
}
}
}
代码如下(示例):(index.js)
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
// reject('error')
}, 2000)
})
promise.then(value => console.log(value), reason => console.log(reason))
console.log(promise); // 此时处于等待期
// console.log(promise) 是处于主线程中的方法,会立即执行, 因此,打印顺序如下
/* -- 打印结果:
Promise:{
status: 'pending',
value: undefined,
reason: undefined,
successCallback: [Function],
failCallback: [Function],
resolve: [Function: resolve],
reject: [Function: reject]
}
111
*/
在上面的代码中,我们是通过将成功回调和失败回调存储起来的方法,来解决Promise中的异步操作的。在上述代码中,我们只调用了一次 then方法,但其实同一个promise对象下面的then方法是可以被多次调用添加多个处理函数的。并且,当then方法被多次调用时,每一个then方法都是要被执行的。
代码如下(示例):(promise.js)
......
class Promise {
......
successCallback = [] // 多次调用,储存多个成功回调函数
failCallback = [] // 多次调用,储存多个失败回调函数
resolve = value => {
......
// 此时是多次调用then方法的写法
while (this.successCallback.length) {
this.successCallback.shift()(this.value)
}
}
reject = reason => {
......
// 此时是多次调用then方法的写法
while (this.failCallback.length) {
this.failCallback.shift()(this.reason)
}
}
then (successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else { // 等待期
// 处理异步操作
/*
当我们多次调用then方法时,我们应该将每一次的成功回调和失败回调都储存起来
因此,我们应该使用数组的形式,储存每一次调用then方法后指定的成功回调和失败回调
*/
// 此时多次调用then方法的写法
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
}
}
代码如下(示例):(index.js)
......
// 调用三次 then方法
promise.then(value => console.log(value), reason => console.log(reason))
promise.then(value => console.log(value), reason => console.log(reason))
promise.then(value => console.log(value), reason => console.log(reason))
console.log(promise); // 此时处于等待期
/* -- 打印结果:
Promise:{
status: 'pending',
value: undefined,
reason: undefined,
successCallback: [ [Function], [Function], [Function] ],
failCallback: [ [Function], [Function], [Function] ],
resolve: [Function: resolve],
reject: [Function: reject]
}
111
111
111
*/
在上面的代码中,我们展示了同一个 Promise对象调用多次 then方法添加多个处理函数的情况。但是有时在实际开发中,我们在调用下一个then方法时,我们需要借助上一个then方法中的返回值,这有点类似我们在上面所说的回调嵌套,在上面我们说到,如果使用回调函数的写法,很容易导致 回调地域 的情况的发生。那么,我们在 Promise中是否有办法解决这个问题呢?
其实,在 Promise是提供了这样的功能的,就是利用 then方法的链式调用。下面,我们就来具体的看一下 then方法的链式调用的实现。
-
为了节省篇幅,以下代码,只分析 成功时的情况,最后会补全失败和等待期的代码
-
首先,我们先来看一下 then方法中值传递的情况。
代码如下(示例):(promise.js)
......
class Promise {
......
/* -- 逻辑分析:
1、调用 then方法的,必须是一个 Promise对象,因此在执行then方法后,需要返回一个promise对象;
2、我们需要把上一个then方法中的回调函数的返回值传递给下一层then方法的回调函数,
因此我们需要,调用执行完上一个then方法后,返回的新的 promise2对象中的执行器中的resolve函数
*/
then (successCallback, failCallback) {
// 1. 实现了 让then方法返回 promise对象
// 传入执行器, 立即执行
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
// 2. 实现把上一个then方法中的回调函数的返回值传递给下一层then方法的回调函数
let x = successCallback(this.value) // x = 111
// x 为成功回调函数的返回值,并将其传递给下一层then方法的回调函数中
// 调用 resolve(x)方法,把上一层then方法返回的值传递给下层then方法的成功回调函数
resolve(x)
} else if (this.status === REJECTED) {
// 失败回调函数,将传入reject函数中传入的原因进行传入
failCallback(this.reason)
} else {
// 等待期
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
return promise2;
}
}
代码如下(示例):(index.js)
let promise = new Promise((resolve, reject) => {
resolve(111);
})
promise.then(value => {
console.log(value) // 111
return 1;
}).then(value => {
console.log(value) // 1
return value
}).then(value => console.log(value)) // 1
.then(value => console.log(value)) // undefined
注意 要想实现 then方法的链式调用,上一层的成功回调函数必须有 return 返回值,否则,下层then方法是获取不到上层then方法中的返回值的。
由于在成功函数和失败函数以及等待期时,执行的操作应该是相同的操作,那么,在下面我们将单独封装一个函数,实现代码重用,减少代码冗余。
- 下面我们再来看一下,then方法中返回 promise对象的情况。
代码如下(示例):(promise.js)
......
class Promise {
......
then (successCallback, failCallback) {
// 1. 实现了 让then方法返回 promise对象
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
let x = successCallback(this.value)
// 判断 x 的值是 普通值 还是 promise对象 封装函数
resolvePromise(x, resolve, reject)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// 等待期
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
return promise2;
}
}
function resolvePromise (x, resolve, reject) {
/** -- 逻辑分析
* 判断 x 的值是 普通值 还是 promise对象
* 如果是普通值,直接调用 resolve
* 如果是 promise对象 查看 promise对象返回的结果
* 再根据 promise 对象返回的结果 决定调用 resolve 还是调用 reject
*/
if (x instanceof Promise) { // x 是promise的情况
/* x 的打印情况
Promise:{
status: 'fulfilled',
value: 'new promise',
reason: undefined,
successCallback: [ [Function], [Function], [Function] ],
failCallback: [ [Function], [Function], [Function] ],
resolve: [Function: resolve],
reject: [Function: reject]
}
*/
// x.then(value => resolve(value), reason => reject(reason))
x.then(resolve, reject) // 代码简化
} else { // x 是 值 的情况
resolve(x)
}
}
代码如下(示例):(index.js)
function other () {
return new Promise((resolve, reject) => { resolve('new promise') })
}
let promise = new Promise((resolve, reject) => { resolve(111) })
promise.then(value => {
console.log(value); // 111
return other();
}).then(value => console.log(value) }) // new promise
在上面的代码中,我们是单独创建了一个新的 promise对象进行返回的。但我们在使用的时候可以看到,如果返回当前的 promise对象,会出现下面的错误。
代码如下(示例):(test.html)
let promise = new Promise(function (resolve, reject) { resolve(100) });
let p1 = promise.then(value => {
console.log(value);
return p1;
})
p1.then(value => console.log(value) }, reason => console.log(reason))
报错信息:
那么,我们该如何识别 promise对象自返回呢?
代码如下(示例):(promise.js)
......
class Promise {
......
then (successCallback, failCallback) {
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
/*
由于这里属于程序运行过程中,而promise2是在程序执行完成后创建的,
因此,我们可以将下面的代码使用定时器转换为异步代码。
由于我们使用定时器只是为了转换,不是为了延时,因此我们需要将时间设为0
*/
setTimeout(() => {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
}
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// 等待期
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 判断是否是自己调用自己, 如果识别了 promise对象在自返回,那么我们模拟需要抛出下面的错误,并使用 return 阻止程序往下运行
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
......
}
在上面的代码中,我们的代码其实并不完善,很多可能发生的错误并没有被捕获,那么下面我们来对代码进行一下补充和完善,使它用起来更加健壮。
代码如下(示例):(promise.js)
// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {
constructor(executor) {
// 捕获执行器的错误
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value => {
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
while (this.successCallback.length) {
this.successCallback.shift()() // 在成功回调函数中已经进行了操作,因此就不用再传值了
}
}
reject = reason => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while (this.failCallback.length) {
this.failCallback.shift()() // 在失败回调函数中已经进行了操作,因此就不用再传值了
}
}
then(successCallback, failCallback) {
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
} else {
// 等待期
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject回调函数
reject(e);
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
}
})
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
module.exports = Promise;
代码如下(示例):(index.js)
const Promise = require('./promise')
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 2000)
// throw new Error('executor error')
// resolve(111)
// reject('error')
})
promise.then(value => {
console.log(value); // 2秒以后,111
return 'aaa';
}, reason => {
console.log(reason);
// throw new Error('then error')
return 111;
}).then(value => console.log(value)) // 'aaa'
截至到目前为止,我们已经完成了 Promise类的核心逻辑,但是在上面所写的 then方法中,我们所传入的参数是必须要传入的,否则后面执行的then方法是无法获取到值的。
代码如下(示例):(index.js)
let promise = new Promise((resolve, reject) => {
resolve(111)
})
promise.then().then(value => console.log(value)) // 未进行值传递,没有打印
那么,我们如何将 then方法中的参数变成可选参数,以便当不传递参数时,promise状态会依次向下传递,直到传递给有回调函数的then方法?
代码如下(示例):(promise.js)
......
class Promise {
......
then (successCallback, failCallback) {
// 判断successCallback是否存在,
// 如果存在时,等于原值;如果不存在,则将值往下进行传递
// failCallback 同理
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => reason;
......
}
}
代码如下(示例):(index.js)
let promise = new Promise((resolve, reject) => {
resolve(111)
})
promise.then().then(value => console.log(value)) // 进行值传递,打印:111
讲到这里,我们已经实现了 Promise的then方法,那么下面我们来介绍一个处理并发问题的API。
Promise.all()
Promise.all()用于将多个 Promise 实例,包装成一个新的 Promise 实例,并且作为返回值返回,且可以链式调用then方法。Promise.all() 允许异步代码按照异步代码调用的顺序,得到结果。并且接收一个数组作为参数,数组中元素的顺序一定是我们得到的结果的顺序。
特点:
1、在all方法中所有的promise对象的状态都是成功的,那么最后的结果就是成功的;
2、在all方法中存在一个promise对象的状态是失败的,那么最后的结果就是失败的。
下面,我们来模拟一下 all 方法的实现过程。
代码如下(示例):(promise.js)
......
class Promise {
......
static all(array) {
// 一、首先需要返回一个 promise对象实例,并且传入一个生成器,立即执行
let result = []; // 结果数组
let index = 0;
return new Promise((resolve, reject) => {
/* 逻辑分析
二、我们需要对传入的数组进行遍历
三、需要判断数组中的每一项元素是 promise对象 还是普通值
1、如果是普通值,那么直接放到结果数组中;
2、如果是 promise对象,则需要先执行这个 promise对象,然后再把返回的结果放到结果数组中
*/
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof Promise) { // 传入的是 promise对象
// 可以链式调用then方法
current.then(value => addData(i, value), reason => reject(reason))
} else { // 普通值
addData(i, array[i])
}
}
// 给结果数组赋值
function addData (key, value) {
result[key] = value;
/*
四、由于for循环的执行是很快的,如果传入的 promise对象中含有异步操作,
那么很有可能结果数组中会出现空值的情况
即 [ '1', '2', <1 empty item>, 'p2' ]
*/
index++;
// 等待所有异步操作都完成,才要执行resolve
if (index === array.length) {
resolve(result) // 结果数组进行赋值时,才会调用resolve, 使之执行顺序和传入顺序一致
}
}
})
}
}
代码如下(示例):(index.js)
function p1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
}
function p2 () {
return new Promise((resolve, reject) => {
resolve('p2')
})
}
Promise.all(['1', '2', p1(), p2(), 3]).then(value => {
console.log(value); // [ '1', '2', 'p1', 'p2', 3 ]
})
在上面的代码中,我们都是自己创建的 promise对象。那么,有没有一个方法可以将普通的值或对象等转换成 promise对象呢?
其实,在Promise类中是提供了这样一个方法的,即 Promise.resolve()。
Promise.resolve()
Promise.resolve()的作用,就是将给定的值转换成 promise对象,也就是说,返回值就是一个 promise对象。
接下来我们来看一下,resolve()方法的代码实现过程。
代码如下(示例):(promise.js)
......
class Promise {
......
static resolve (value) {
/*
判断 value 是 promise对象,还是普通值
如果是 promise对象,则直接返回
如果是 普通值,使用resolve将传入的值进行包裹,然后返回这个新建的 promise对象
*/
if (value instanceof Promise) {
return value;
} else {
return new Promise(resolve => resolve(value));
}
}
}
代码如下(示例):(index.js)
function p2 () {
return new Promise((resolve, reject) => {
resolve('p2')
})
}
Promise.resolve(1).then(value => console.log(value)) // 1
Promise.resolve(p2()).then(value => console.log(value)) // p2
Promise.prototype.finally()
finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
- 特点
1、无论 promise对象最终的状态是成功的还是失败的,finally方法中的回调函数始终都会被执行一次;
2、可以在 finally方法的后面链式调用then方法,拿到这个 promise对象最终返回的结果。
代码如下(示例):(promise.js)
.....
class Promise {
......
finally (callback) {
/* 逻辑分析
无论当前promise的状态成功还是失败,都要执行callback这个回调函数
首先,要获取当前 promise对象的状态,可以通过then方法获取;
然后,需要在finally方法的后面链式调用then方法,要返回一个 promise对象
因此可以直接返回then方法返回的 promise对象;
接着,需要再次调用then方法,需要拿到当前then方法中promise对象的结果,并将其return
最后,如果promise对象返回的结果中包含异步逻辑,
而此时then方法可能不会等到异步操作执行完成,就直接执行了
那么需要使用 Promise.resolve()方法,查看一下callback中的返回值,是普通值 还是 promise对象, 无论是什么,都等待其完成
*/
return this.then(value => {
return Promise.resolve(callback()).then(() => value);
}, reason => {
// 传递错误原因
return Promise.resolve(callback()).then(reason => { throw reason });
})
}
......
}
代码如下(示例):(index.js)
function p1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
}
function p2 () {
return new Promise((resolve, reject) => {
resolve('p2')
})
}
p2().finally(() => {
console.log('finally');
return p1();
// return 100;
}).then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
Promise.prototype.catch()
catch方法用来处理当前 promise对象最终的状态为失败的情况的,内部注册的只有失败回调,成功回调返回undefined。
代码如下(示例):(promise.js)
catch (failCallback) {
return this.then((undefined, failCallback))
}
代码如下(示例):(index.js)
function p2 () {
return new MyPromise((resolve, reject) => {
resolve('p2')
})
}
p2().then(value => console.log(value))
.catch(reason => console.log(reason))
总结
在上面的代码中,我们详细分析了Promise 底部核心逻辑的实现过程。最后在此附上全部的代码,希望对看到这篇文章的朋友们有所帮助。
代码如下(示例):(promise.js)
// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value => {
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
while (this.successCallback.length) {
this.successCallback.shift()()
}
}
reject = reason => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while (this.failCallback.length) {
this.failCallback.shift()()
}
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => reason;
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
}
})
return promise2;
}
finally (callback) {
return this.then(value => {
return Promise.resolve(callback()).then(() => value);
}, reason => {
return Promise.resolve(callback()).then(reason => { throw reason });
})
}
static all(array) {
let result = [];
let index = 0;
return new Promise((resolve, reject) => {
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof Promise) {
current.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, array[i])
}
}
function addData (key, value) {
result[key] = value;
index++;
if (index === array.length) {
resolve(result)
}
}
})
}
static resolve (value) {
if (value instanceof Promise) {
return value;
} else {
return new Promise(resolve => resolve(value));
}
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
module.exports = Promise;