Open Hongbusi opened 2 years ago
前面那个判断能去掉吗,里面已经判断了嘛
支持 HBS & developer-plus🏅 补充一个答案
/**
* 分析
* 1. 通过 new Promise 语法发现 ,Promise 就是一个类 ,并且在创建这个类的时候需要一个参数,它会立即执行
*
* 2. Promise 中有3中状态,分别为 成功 fulfilled、失败 rejected 、等待 pending
* 状态走向:
* pending -> fulfilled
* or
* pending -> rejected
* 只要状态确定,将不可更改。
*
* 3. resolve 和 reject 就是用来更改状态的
* resolve:fulfilled
* reject:rejected
*
* 4. then 方法判断状态 成功调用成功回调,失败调用失败回调函数
*
* 5. 成功回调有一个参数 表示成功之后的值,失败回调也有一个参数表示失败之后的值
*
* 6. 通过 new 出来的 promise 对象 只有 then 、catch 方法成员,所以 status 、value 、等是私有属性,外部无法访问
* 为了防止直接通过 promise.status 进行修改状态
*
*/
/**
* 等待
*/
const PENDING = "pending";
/**
* 成功
*/
const FULFILLED = "fulfilled";
/**
* 失败
*/
const REJECTED = "rejected";
/**
* 私有属性
* 在最新的 ES 规范中 以及有 private 关键字 来设置私有属性,这样更直观、简单
* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields
*
* 当然在 TypeScript 中已经支持此特性。
*/
const _status = Symbol();
const _value = Symbol();
const _reason = Symbol();
const _resolve = Symbol();
const _reject = Symbol();
const _successCallback = Symbol();
const _failCallback = Symbol();
class MyPromise {
constructor(executor) {
// 私有属性初始化
// 初始化为数组 解决 多次 promise.then() 情况
this[_successCallback] = [];
this[_failCallback] = [];
/**
* 成功方法
*/
this[_resolve] = (value) => {
// 如果状态不是等待中,直接return
if (this[_status] !== PENDING) return;
// 状态改为成功
this[_status] = FULFILLED;
// 保存成功的值
this[_value] = value;
// 如果成功回调存在就调用执行它
// this[_successCallback] && this[_successCallback](value)
while (this[_successCallback].length) this[_successCallback].shift()();
};
/**
* 失败方法
*/
this[_reject] = (reason) => {
// 如果状态不是等待中,直接return
if (this[_status] !== PENDING) return;
// 状态改为失败
this[_status] = REJECTED;
// 保存失败的值
this[_reason] = reason;
// 如果失败回调存在就调用执行它
// this[_failCallback] && this[_failCallback](reason)
while (this[_failCallback].length) this[_failCallback].shift()();
};
/**
* promise 状态 初始化
*/
this[_status] = PENDING;
// 立即执行执行器 并捕获错误
try {
executor(this[_resolve], this[_reject]);
} catch (error) {
this[_reject](error);
}
}
then(successCallback, failCallback) {
// 处理then 参数可选情况
successCallback = successCallback ? successCallback : (value) => value;
failCallback = failCallback
? failCallback
: (reason) => {
throw reason;
};
// then 链式调用 所以需要返回 MyPromise
const promise = new MyPromise((resolve, reject) => {
// 判断状态 是 成功 还是 失败
if (this[_status] === FULFILLED) {
// 写成异步 让new MyPromise 先创建完成
setTimeout(() => {
try {
const prevVal = successCallback && successCallback(this[_value]);
resolvePromise(promise, prevVal, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this[_status] === REJECTED) {
// 写成异步 让new MyPromise 先创建完成
setTimeout(() => {
try {
const prevVal = failCallback && failCallback(this[_reason]);
resolvePromise(promise, prevVal, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 异步情况
// 把回调函数储存起来 当异步代码执行 resolve or reject 时执行回调函数
this[_successCallback].push(() => {
// 写成异步 让new MyPromise 先创建完成
setTimeout(() => {
try {
const prevVal = successCallback && successCallback(this[_value]);
resolvePromise(promise, prevVal, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this[_failCallback].push(() => {
// 写成异步 让new MyPromise 先创建完成
setTimeout(() => {
try {
const prevVal = failCallback && failCallback(this[_reason]);
resolvePromise(promise, prevVal, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise;
}
finally(callback) {
return this.then(
(value) => {
return MyPromise.resolve(callback()).then(() => value);
},
(reason) => {
return MyPromise.resolve(callback()).then(() => {
throw reason;
});
}
);
}
catch(failCallback) {
return this.then(undefined, failCallback);
}
static all(arr) {
let result = [];
let index = 0;
// 返回一个promise 对象
return new MyPromise((resolve, reject) => {
function add(key, value) {
result[key] = value;
index++;
if (index === arr.length) {
resolve(result);
}
}
for (let i = 0; i < arr.length; i++) {
const elem = arr[i];
if (elem instanceof MyPromise) {
elem.then(
(value) => add(i, value),
(reason) => reject(reason)
);
} else {
add(i, elem);
}
}
});
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve) => resolve(value));
}
}
// 辅助方法
/**
* 判断 prevVal 是普通值还是 promise 对象
*
* 如果是普通值 直接调用 resolve
*
* 如果是 promise 对象 先查看 promise 对象的结果
* 再根据 返回的结果 决定调用 resolve or reject
*
* 处理 prev 是普通值还是 promise 对象
*/
const resolvePromise = (promise, prevVal, resolve, reject) => {
// 判断自己返回自己
if (promise === prevVal) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (prevVal instanceof MyPromise) {
// prevVal.then(value => resolve(value, reason => reject(reason))
prevVal.then(resolve, reject);
} else {
// 普通值
resolve(prevVal);
}
};
MyPromise.defer = MyPromise.deferred = function () {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = MyPromise;
BaboonKing🙈
type ResolveType = (value: any) => void
type RejectType = (value: any) => void
type Executor = (resolve: ResolveType, reject: RejectType) => void
export class Promise<T=any> {
public resolve!: ResolveType
public reject!: RejectType
public status!: string
public resolve_executor_value!: any
public reject_executor_value!: any
public resolve_callbacks = []
public reject_callbacks = []
constructor(executor: Executor) {
this.status = 'pending' // 起始等待状态
this.resolve = (successvalue: any): any => {
if(this.status !== 'pending') return
this.status = 'success'
this.resolve_executor_value = successvalue
this.resolve_callbacks.forEach((callback) => callback())
}
this.reject = (failvalue: any): any => {
if(this.status !== 'pending') return
this.status = 'fail'
this.reject_executor_value = failvalue
this.reject_callbacks.forEach((callback) => callback())
}
try {
executor(this.resolve, this.reject)
} catch (err) {
this.status = 'pending'
this.reject(err.toString())
throw new Error('程序终止')
}
}
then(resolveInthen: ResolveType, rejectInthen :RejectType) {
return new Promise((resolve, reject) => {
let result
if(this.status === 'pending') {
this.resolve_callbacks.push(() => {
result = resolveInthen(this.resolve_executor_value)
if (isPromise(result)) {
result.then((res) => { // res 就是后面一次进来时赋成了 this.resolve_executor_value
resolve(res) // 这个地方的 resolve 是 then 中异步 promise 的,而下面的 resolve 是原来的 promise 的,不能混用,所以这里我直接在这调用
}, (err) => { // 这个地方的 then 其实是存给 result 所代表的 promise,而不是 else 中的那个 promise
reject(err)
})
} else {
resolve(result)
}
})
this.reject_callbacks.push(() => {
result = rejectInthen(this.reject_executor_value)
if (isPromise(result)) {
result.then((res) => { // res 就是后面一次进来时赋成了 this.resolve_executor_value
resolve(res) // 这个地方的 resolve 是 then 中异步 promise 的,而下面的 resolve 是原来的 promise 的,不能混用,所以这里我直接在这调用
}, (err) => { // 这个地方的 then 其实是存给 result 所代表的 promise,而不是 else 中的那个 promise
reject(err)
})
} else {
reject(result)
}
})
} else {
if (this.status === 'success') {
resolve(resolveInthen(this.resolve_executor_value))
}
if (this.status === 'fail') {
reject(rejectInthen(this.reject_executor_value))
}
}
})
}
static all(promiseArr: Array<Promise>): Promise {
return new Promise((resolve, reject) => {
let allPromiseResolveSVal = []
let new_index = 0
promiseArr.forEach((promise, index) => {
promise.then((res) => {
process(res, index)
}, (rejectFail) => {
reject(rejectFail)
return
})
})
function process(sval, index) {
allPromiseResolveSVal[index] = sval
if (new_index === promiseArr.length - 1) {
resolve(allPromiseResolveSVal)
}
new_index++
}
})
}
}
function isPromise(val: any): val is Promise {
return typeof val === 'object' && typeof val.then === 'function'
}
export {}
@luckept
可以在代码块加一个类型,使代码高亮。
``` ts
@luckept
可以在代码块加一个类型,使代码高亮。
``` ts
哈哈哈好!
Promise
是 ES6 中新增的引用类型。在通过
new
创建Promise
对象时,需要传入一个回调函数(executor)。resolve
、reject
;resolve
回调函数时,会执行Promise
对象then
方法传入的回调函数;reject
回调函数时,会执行Promise
对象的catch
方法传入的回调函数。3 种状态
pending
:执行executor
中的代码时,处于该状态;fulfilled
:执行了resolve
时,处于该状态;rejected
:执行了reject
时,处于该状态。9 个方法
then
:当调用resolve
回调函数时,会执行;catch
:当调用reject
回调函数时,会执行;finally
:无论是fulfilled
状态,还是reject
状态,它都会执行;resolve
:相当于new Promise
,并且执行resolve
操作;reject
:相当于new Promise
,并且执行reject
操作;all
:将多个Promise
包裹在一起形成一个新的Promise
;allSettled
:所有的Promise
都有结果,才会有最终的状态;race
:多个Promise
相互竞争,谁先有结果,那么就使用谁的结果;any
:等到一个fulfilled
状态,才会决定新Promise
的状态。如果所有的Promise
都是reject
的,那么会报一个AggregateError
的错误。手写 Promise 思路
一、Promise 类设计
二、构造函数的规划
三、then 方法实现
四、catch 方法
五、finally
六、resolve/reject
七、all/allSettled
核心:要知道
new Promise
的resolve
、reject
在什么情况下执行。all
:情况一:所有的都有结果; 情况二:有一个
reject
。allSettled
:情况:所有都有结果,并且一定执行
resolve
。八、race/any
race
:情况:只要有结果。
any
:情况一:必须等到一个
resolve
结果; 情况二:都没有resolve
,所有的都是reject
,报一个AggregateError
的错误。手写 Promise