предисловие
мы все знаем,then
метод возвращает новыйpromise
экземпляр, который является основой для реализации связанных вызовов.
чтобыpromise
При изменении состояния (resolve
/ reject
при вызове), а затем выполнитьthen
функция, мы используемcallbacks
Массив сначала временно хранит переданную потом функцию, а затем вызывает ее при изменении состояния.
Итак, как гарантировать последнееthen
Метод в предыдущемthen
(возможно, асинхронно), а затем выполнить его после окончания?
Например, в следующем примере последнийthen
должен быть напечатан через 2 секунды со значением 2
var p1 = new MyPromise((resolve, reject) => {
console.log('hhh')
setTimeout(() => {
resolve(1)
}, 1000);
}).then(res => {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(res+1)
}, 1000);
})
}).then(res => {
console.log(res);
return res;
})
Ядро реализации связанных вызовов
будет переданоthen
функции и новыеpromise
изresolve
Вместеpush
к предыдущемуpromise
изcallbacks
В массиве добиться эффекта связи прошлого и будущего
- Преемственность: текущая
promise
Когда закончите, вызовите егоresolve
изменить статус, в этомresolve
будет вызываться по очередиcallbacks
Обратный вызов, это будет выполненоthen
метод в - После старта: на предыдущем шаге, когда
then
После выполнения метод возвращает результат. Если результатом является простое значение, он напрямую вызывает новый метод.promise
изresolve
, пусть его состояние изменится, что, в свою очередь, вызовет новыйpromise
изcallbacks
Методы в массиве повторяются в цикле. . Если возвращаемый результат являетсяpromise
, вам нужно дождаться его завершения, прежде чем запускать новыйpromise
изresolve
, поэтому его можно найти в его результатеthen
вызовите новыйpromise
изresolve
Реализация кода тогда:
then(onFulfilled, onReject){
// 保存前一个promise的this
const self = this;
return new MyPromise((resolve, reject) => {
// 封装前一个promise成功时执行的函数
let fulfilled = () => {
try{
const result = onFulfilled(self.value); // 承前
return result instanceof MyPromise? result.then(resolve, reject) : resolve(result); //启后
}catch(err){
reject(err)
}
}
// 封装前一个promise失败时执行的函数
let rejected = () => {
try{
const result = onReject(self.reason);
return result instanceof MyPromise? result.then(resolve, reject) : reject(result);
}catch(err){
reject(err)
}
}
switch(self.status){
case PENDING:
self.onFulfilledCallbacks.push(fulfilled);
self.onRejectedCallbacks.push(rejected);
break;
case FULFILLED:
fulfilled();
break;
case REJECT:
rejected();
break;
}
})
}
Внимание ⚠️
- несколько подряд
then
Метод обратного вызова регистрируется синхронно, но регистрируется в другомcallbacks
массив, потому что каждый разthen
оба возвращают новыеpromise
Примеры (см. примеры и рисунки выше) - После завершения регистрации выполняются асинхронные события в конструкторе, а асинхронные события вызываются последовательно после асинхронного завершения.
callbacks
Обратные вызовы, зарегистрированные заранее в массиве
Итак, при каких обстоятельствахcallbaks
Как насчет нескольких обратных вызовов в массиве?
Например это:
p1
Когда закончите, зарегистрируйтесь наp1
изcallbacks
Функции в выполняются последовательно
Следующий код печатает 1 через 1 секунду и 2 через 2 секунды.
var p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000);
})
var p2 =p1.then(res => { //p1完成时的回调1
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(res+1)
}, 1000);
})
}).then(res => {
console.log(res); // 2
return res+1;
})
p1.then(res => { // p1完成时的回调2
console.log(res); // 1
})
Однако, если вы напишете:
var p1 = new MyPromise((resolve, reject) => {
console.log('hhh')
setTimeout(() => {
resolve(1)
}, 1000);
}).then(res => {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(res+1)
}, 1000);
})
}).then(res => {
console.log(res); // 2
return res+1;
})
p1.then(res => {
console.log(res); // 3
})
последнийp1.then
печатается в конце, потому чтоp1
Возвращаемое значение является третьимpromise
,последнийthen
Функция in также прописана в третьемpromise
изcallbacks
середина.
Полная реализация обещания
// 定义三种状态
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECT = 'REJECT';
class MyPromise {
constructor(fn){
// 初始化状态
this.status = PENDING;
// 将成功、失败的结果放在this上,便于then、catch访问
this.value = null;
this.reason = null;
// 成功态、失败态回调函数队列,同步调用then时将对应态的函数注册进去, 在状态变更的时候调用
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value;
// 成功态回调函数依次执行
this.onFulfilledCallbacks.forEach(fn => fn(this.value))
}
}
const reject = (reason) => {
if(this.status === PENDING){
this.status = REJECT;
this.reason = reason;
// 失败态回调函数依次执行
this.onRejectedCallbacks.forEach(fn => fn(this.reason))
}
}
// 生成实例后立即调用fn
// 把内部的resolve和reject传入fn,用户可调用resolve和reject
try{
fn(resolve, reject);
}catch(err){
// fn执行出错,将错误内容用reject抛出去
reject(err)
}
}
then(onFulfilled, onReject){
// 实现值穿透 当then中传入的不是函数,则这个promise返回上一个promise的值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onReject = typeof onReject === 'function' ? onReject : reason => { throw new Error(reason) }
// 保存前一个promise的this
const self = this;
return new MyPromise((resolve, reject) => {
// 封装前一个promise成功时执行的函数
let fulfilled = () => {
try{
const result = onFulfilled(self.value); // 承前
return result instanceof MyPromise? result.then(resolve, reject) : resolve(result); //启后
}catch(err){
reject(err)
}
}
// 封装前一个promise失败时执行的函数
let rejected = () => {
try{
const result = onReject(self.reason);
return result instanceof MyPromise? result.then(resolve, reject) : reject(result);
}catch(err){
reject(err)
}
}
switch(self.status){
case PENDING:
self.onFulfilledCallbacks.push(fulfilled);
self.onRejectedCallbacks.push(rejected);
break;
case FULFILLED:
fulfilled();
break;
case REJECT:
rejected();
break;
}
})
}
// Promise.prototype.catch就是Promise.prototype.then(null, onRejected)的别名
catch(onRejected){
return this.then(null, onRejected);
}
static resolve(value){
// 如果是promise实例,直接返回
if(value instanceof MyPromise){
return value;
}else{
// 如果不是promise实例,返回一个新的promise对象,状态为fulfilled
return new MyPromise((resolve, reject) => resolve(value))
}
}
static reject(reason){
// Promise.reject方法的参数会原封不动地作为reject的参数
return new MyPromise((resolve, reject) => reject(reason))
}
/**
* Promise.all() 接受一个数组,返回一个promise对象
* 所有的promise状态变为FULFILLED,返回的promise状态才变为FULFILLED。
* 一个promise状态变为REJECTED,返回的promise状态就变为REJECTED。
* 数组成员不一定都是promise,需要使用Promise.resolve()处理。
*/
static all(promiseArr){
const len = promiseArr.length;
const values = new Array(len);
let count = 0; // 记录已经成功的promise个数
return new MyPromise((resolve, reject) => {
for(let i=0; i<len; i++){
// Promise.resolve()处理,确保每一个都是promise实例
MyPromise.resolve(promiseArr[i]).then(
val => {
values[i] = val;
count++;
if(count === len) resolve(values); // 如果全部执行完,改变promise的状态为FulFilled
},
err => {
reject(err)
}
)
}
})
}
static race(promiseArr){
return new MyPromise((resolve, reject) => {
promiseArr.forEach(item => {
MyPromise,resolve(item).then(
val => resolve(val),
err => reject(err)
)
})
})
}
}