手写 promise
promise 基本特征
- 有三个状态:pengding、fullfilled、rejected
- new Promise 时,需要传递一个回调,立即执行
- 回调接受两个参数,resolve 和 reject
- 默认状态是 pending
- promise 有一个 value 保存成功状态的值,可以是 undefined、thenable、promise
- promise 有一个 reason 保存失败状态的值
- promise 智能从 pending 到 rejected 或者 fullfilled,状态一旦确认就不会再改变
- promise 必须有一个 then 方法,接受两个参数,分别是成功的回调 onFulfilled 和失败的回调 onRejected
- 如果调用 then,promise 已经成功,则执行 onFullfilled,参数是 promise 的 value
- 如果调用 then,promise 已经失败,调用 onRejected,参数是 promise 的 reason
- 如果 then 抛出异常,那么就把异常作为参数,传给下一个 then 的失败的回调 onRejected
- then的参数onFulfilled和onRejected可以缺省,如果不是函数,就忽略,且依旧可以在下面的then中获取到之前返回的值
- promise可以then多次,每次都返回新的promise
- 如果promise返回一个普通值,就把这个结果作为参数,传递给下一个then的成功回调
- 如果promise抛出异常,那么这个异常作为参数传递给下一个then的失败回调
- 如果返回一个promise,会等这个promise执行完,如果成功就走下个then,如果失败或者抛出异常就走下个的失败
- 如果then的返回值和promise是同一个引用对象,造成循环引用,那就抛出异常
- 如果then的返回值是一个promise,且x同时调用resolve和reject,第一个调用优先,状态不会再次被改变
js
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
const resolvePromise = (promise, x, resolve, reject) => {
if (promise === x) return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
let called = false;
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
};
class MyPromise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
let reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
static resolve(value) {
if (value instanceof Promise) {
return value;
} else {
return new MyPromise((resolve, reject) => {
resolve(value);
});
}
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected =
typeof onRejected === 'function'
? onRejected
: err => {
throw err;
};
let promise = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise;
}
}
MyPromise.prototype.catch = function (cb) {
return this.then(null, cb);
};
MyPromise.prototype.finally = function (cb) {
return this.then(
value => {
return MyPromise.resolve(cb()).then(() => value);
},
reason => {
return MyPromise.resolve(cb()).then(() => {
throw reason;
});
}
);
};
MyPromise.all = function (values) {
if (!Array.isArray(values)) {
const type = typeof values;
return new TypeError(`TypeError: ${type} ${values} is not iterable`);
}
return new MyPromise((resolve, reject) => {
let resultArr = [];
let orderIndex = 0;
const processResultByKey = (value, index) => {
resultArr[index] = value;
if (++orderIndex === values.length) {
resolve(resultArr);
}
};
for (let i = 0; i < values.length; i++) {
let value = values[i];
if (value && typeof value.then === 'function') {
value.then(value => {
processResultByKey(value, i);
}, reject);
} else {
processResultByKey(value, i);
}
}
});
};
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i > promises.length; i++) {
let val = promises[i];
if (val && typeof val.then === 'function') {
val.then(resolve, reject);
} else {
resolve(val);
}
}
});
};
// const promise = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve('成功');
// }, 1000);
// }).then(
// data => console.log('resolve', data),
// err => console.log('reject', err)
// );
const promise1 = new MyPromise((resolve, reject) => {
reject('失败');
})
.then()
.then()
.catch(err => {
console.log('promise1 err1', err);
})
.catch(err => {
console.log('promise1 err2', err);
});
// MyPromise.deferred = function () {
// let dfd = {};
// dfd.promise = new MyPromise((resolve, reject) => {
// dfd.resolve = resolve;
// dfd.reject = reject;
// });
// return dfd;
// };
// module.exports = MyPromise;
export default MyPromise;
promise的方法实现
js
static resolve(data){
if(data instanceof Promise){
}
}