前言
很久很久以前,手写过一个promise1.0,今天 是对其做一些补充。
x返回的是一个promise对象处理
思路
If promise and x refer to the same object, reject promise with a TypeError as the reason.
如果promise2===x的时候 文档是要求拒绝这个promise 执行reject
if (promise2 === x) {
return reject(new TypeError("错误"));
}
Otherwise, if x is an object or function,
if ((typeof x === "object" && x !== null) || typeof x === "function") {}
- 挑了我看得懂的部分 (阅读水平就这么回事了,求勿喷)
- let then = x.then;
Let then be x.then - 捕获上一个then的错误 做参数传给 这个then的 catch
If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason. - then是一个函数,this指向x,第一参数 里 resolvePromise(promise2, y, resolve, reject);递归,继续判断下一个then,直到x是普通值,然后resolve(x),第二参数里,直接reject(r)
If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, whereIf/when resolvePromise is called with a value y, run [[Resolve]](promise, y).If/when rejectPromise is called with a reason r, reject promise with r
代码
// 利用x的值来判断是调用promise的resolve还是reject
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("错误"));
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called = false;
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
//then就是一个空对象{},或者 {then:{}}
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
// x返回值是一个普通值,直接传入promises2的resolve中
resolve(x);
}
}
调用
- class Promise 上的
then方法里if (this.status === FULFILLED) - 顺便做一个优化,包裹setTimeout ,then也是异步的 所以用setTimeout包裹,否则resolvePromise拿不到promise2
- 上一个then执行结果x作为当前then的resolve的入参数 1. 这里要注意 只要上一个then有return 值 就调用当前then的resolve 捕获了异常才调用reject 2. x的值可能是一个promise,如果是promise需要看下这个promise是成功还是失败 3. 如果成功 则把成功的结果 调用promise2的resolve传递进去,如果失败也同理,直接catch 4. x的值决定调用promise2的resolve还是reject,如果是promise则取他的状态,如果是普通值则调用resolve 5. resolvePromise用于处理 x的返回值
if (this.status === FULFILLED) {
setTimeout(() => {
// 函数执行时的throw Error的处理,
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
// 上一个then执行结果x作为当前then的reject的入参数
let x = onRejected(this.reason);
// 这里要注意 只要上一个then有return 值 就调用当前then的resolve 捕获了异常才调用reject
resolve(x);
} catch (err) {
reject(err);
}
}, 0);
}
Promise 静态方法的实现
resolve
返回一个new Promise 直接调用resolve
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
reject
思路 同 resolve
static reject(value) {
return new Promise((resolve, reject) => {
reject(value);
});
}
all
static all(promises) {
//同步并发
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
const processSuccess = (index, val) => {
result[index] = val;
// 这里为什么不直接用result.length===promises.length
// 无法准确直到 执行结果
if (++times === promises.length) {
resolve(result);
}
};
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
// if (p instanceof Promise)
// if(p&&typeof p.then==='function')
if (p && typeof p.then === "function") {
p.then((data) => {
processSuccess(i, data);
}, reject);
} else {
processSuccess(i, p);
}
}
});
}
race
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
if (p && typeof p.then === "function") {
p.then(resolve, reject); //一旦成功就直接 停止
} else {
resolve(p);
}
}
});
}
Promise 原型方法
catch
catch(errFn) {
return this.then(null, errFn);
}
finally
- 保证cb是一个promise的时候 用Promise.resolve包裹可以保证内部promise执行完毕
- 直接传递上一个promise的执行结果做下一个then的回调函数的参数
finally(cb) {
return this.then(
(data) => {
return Promise.resolve(cb()).then(() => data);
},
(err) => {
return Promise.resolve(cb()).then(() => {
throw err;
});
}
);
}
最后 npm install promise-aplus-test安装promise 测试 做校验
小结:终于把坑填上