promise 是一种处理异步任务和 callback 函数的解决方案。promise 解决了地狱回调问题(多个 callbacks 嵌套在一起),增强了代码可读性。
创建一个 promise
let promise = new Promise(function(resolve, reject){
// executor
})
new Promise() 中传入的函数叫 executor,将异步任务放在 executor 里。promise 一旦被创建,executor 便立刻同步执行。
resolve 和 reject 是内置的回调函数,如果异步任务执行成功,调用 resolve(value); 如果发生错误就调用 reject(error)。
一个 promise 对象有两个内置属性:
- state: 初始为 "pending", 调用
resolve(value)变为 "fulfilled", 调用reject(error)变为 "rejected"。state 只能更改一次。 - result: 初始为 "undefined", 调用
resolve(value)变为 "value", 调用reject(error)变为 "error"。result 只能更改一次。
使用 Promise.prototype.then
promise.then(
result => {
// 处理成功结果
},
error => {
// 处理错误
}
)
promise.then 函数中可传入两个函数,第一个函数 onFulfilled 处理成功结果,第二个函数 onError 处理错误。也可以只传入第一个成功函数。
promise.then() 返回一个 promise, 所以可以链式调用 then 函数。
-
返回的新 promise 取决于传入 then 中回调函数的返回值;
-
回调函数返回普通值,新 promise 中 state 变为 "fulfilled",result 为返回的值;
-
回调函数产生 error,新 promise 中 state 变为 "rejected",result 为 error;
-
回调函数返回一个新 promise,then 返回的 promise 会等回调函数返回的promise先执行且属性取决于新返回的 promise;
使用 Promise.all
let promise = Promise.all([promise1, promise2, ...])
Promise.all 接收一个包含多个 promise 的列表,同时执行多个 promises,然后返回一个新 promise。
如果所有 promise 都成功地执行完毕,返回的新 promise state 变为 "fulfilled",result 就是包含多个 promises 结果的列表。如果其中任何一个 promise 产生错误,Promise.all 立刻返回一个 rejected 的 promise,其他 promises 的结果会被无视。
使用 Promise.race
和 Promise.all 类似,但只返回第一个执行完毕的 promise (不论成功与失败)。
手写一个简易 Promise
class myPromise {
constructor(fn) {
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
this.status = 'pending';
this.value = null;
this.error = null;
let resolve = value => {
let fn = () => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(cb => cb(this.value));
};
setTimeout(fn, 0);
};
let reject = error => {
let fn = () => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.error = error;
this.onRejectedCallbacks.forEach(cb => cb(this.error));
};
setTimeout(fn, 0);
};
fn(resolve, reject);
}
then(onFulfilled, onRejected) {
return new myPromise((resolve, reject) => {
const fulfilled = value => {
try {
if (typeof onFulfilled !== 'function') {
resolve(value);
} else {
const ret = onFulfilled(value);
if (ret instanceof myPromise) {
ret.then(resolve, reject);
} else {
resolve(ret);
}
}
} catch (err) {
reject(err);
}
};
const rejected = error => {
try {
if (typeof onRejected !== 'function') {
reject(error);
} else {
const ret = onRejected(error);
if (ret instanceof myPromise) {
ret.then(resolve, reject);
} else {
resolve(ret);
}
}
} catch (err) {
reject(err);
}
};
switch (this.status) {
case 'pending':
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
break;
case 'fulfilled':
setTimeOut(fulfilled(this.value));
break;
case 'rejected':
setTimeOut(rejected(this.value));
break;
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
// 无论成功和失败都执行 cb
finally(cb) {
return this.then(cb, cb);
}
static resolve(val) {
if (val instanceof myPromise) return val;
return new myPromise(res => res(val));
}
static reject(err) {
return new myPromise((res, rej) => rej(err));
}
static all(promises) {
return new myPromise((res, rej) => {
let result = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
promises[i].then(
val => {
result[i] = val;
count += 1;
if (count === promises.length) {
res(result);
}
},
err => {
rej(err);
}
);
}
});
}
static race(promises) {
return new myPromise((res, rej) => {
for (let i = 0; i < promises.length; i++) {
myPromise.resolve(promises[i]).then(res, rej);
}
});
}
}