1. Promise
Promise
是承诺的意思,承诺在未来会有一个确切的答复,是 ES6 发布的异步编程的一种解决方案。 该承诺有三种状态:pending(等待)
、resolved(完成)
和rejected(拒绝)
,只能从pending
变成其它两种状态,并且状态一旦变化后就不可改变。优点:有效改善异步编程中容易导致的回调地狱问题。缺点:Promise
无法取消,错误需要通过回调函数捕获。
- 定义三个状态常量
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
- 实现 MyPromise
function MyPromise (fn) {
const that = this; // 代码可能异步执行,用于正确找到this
that.value = null; // 用于保存resolve、reject传入的值
that.state = PENDING;
that.resolvedCallbacks = []; // 保存then中的回调,promise执行完后state的状态可能还是PENDING,
that.rejectedCallbacks = []; // 因此要把回调函数保存起来,等待state状态改变时执行
// 实现resolve
function resolve (value) {
if (value instanceof MyPromise) {
return value.then(resolve, reject);
}
setTimeout(() => {
if (that.state === PENDING) { // 只有PENDING状态才可以改变状态
that.state = RESOLVED;
that.value = value;
that.resolvedCallbacks.forEach(cb => cb(that.value)); // 执行回调
}
}, 0)
}
// 实现reject
function reject (value) {
setTimeout(() => {
if (that.state === PENDING) {
that.state = REJECTED;
that.value = value;
that.rejectedCallbacks.forEach(cb => cb(that.value));
}
}, 0)
}
// 执行函数fn
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}
- 实现 then 方法
MyPromise.prototype.then = function (onFulfilled, onRejected) {
const that = this;
// 参数为可选参数,首先判断两个参数是否为函数,如果不是函数,创建一个函数赋值给对应参数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : v => { throw v };
// 如果状态还是PENDING时,往回调函数中push函数,否则执行函数
if (that.state === PENDING) {
that.resolvedCallbacks.push(onFulfilled);
that.rejectedCallbacks.push(onRejected);
}
if (that.state === RESOLVED) {
onFulfilled(that.value);
}
if (that.state === REJECTED) {
onRejected(that.value);
}
}
2. Promise.all
将多个
Promise
实例包装成一个Promise
实例,接收包含Promise
对象或普通值的数组(或其它可迭代对象)作为参数,成功时返回值为Promise
实例数组对应的结果数组,失败时返回第一个rejected
的Promise
实例的结果。
const p1 = new Promise(resolve => { setTimeout(resolve, 200, 1) });
const p2 = new Promise(resolve => { resolve(2) });
const p3 = 3;
console.log(Promise.all([p1, p2, p3])); // [1, 2, 3]
Promise.prototype.all = function (promiseArr) {
let resArr = [], count = 0, len = promiseArr.length;
// 返回一个新的 Promise 实例
return new Promise(function (resolve, reject) {
for (let promise of promiseArr) {
// 数组传进来的项可能不是一个Promise实例,使用Promise.resolve方法转换
Promise.resolve(promise).then(function(res) {
resArr[count] = res;
count++;
if (count === len) {
return resolve(resArr);
}
}, function (err) {
return reject(err);
})
}
})
}
- 使用
async await
达到跟Promise.all
同样效果的方法
var promiseQueue = async (arr) => {
const res = [];
for (let promise of arr) {
res.push(await promise)
}
return await res;
}
promiseQueue([p1,p2,p3]).then(res => { console.log(res) }); // [1,2,3]
3. Promise.race
与
Promise.all
一样,Promise.race
也接收包含Promise
对象或普通值的数组(或其它可迭代对象)作为参数,返回一个Promise
实例对象。与Promise.all
不同的是,一旦有一个Promise
实例对象resolve
,立即把这个resolve
的值作为Promise.race
resolve
的值。一旦有一个对象reject
,Promise.race
也会立即reject
。
Promise.prototype.race = function (promiseArr) {
return new Promise(function (resolve, reject) {
for (let promise of promiseArr) {
if (typeof promise === 'object' && typeof promise.then === 'function') {
// 数组传进来的项是一个Promise实例,执行then方法。
// resolve只有一个,那个实例对象最先执行完就会使用这个resolve
promise.then(resolve, reject);
} else {
// 不是Promise实例对象直接返回当前值
resolve(promise);
}
}
})
}
4. Promise.resolve 和 Promise.reject 的使用
-
Promise.resolve(value)
返回一个以给定值解析后的
Promise
对象。
- 如果该值为
promise
,返回这个promise
; - 如果这个值是带有"then" 方法的,返回的
promise
会“跟随”这个thenable
的对象,采用它的最终状态; - 否则返回的
promise
将以此值完成。
Promise.resolve("Success").then(function(value) {
console.log(value); // "Success"
}, function(error) {
// 不会被调用
});
-
Promise.reject(error)
静态函数
Promise.reject
返回一个被拒绝的Promise
对象。通过使用Error
的实例获取错误原因reason
对调试和选择性错误捕捉很有帮助。
Promise.reject(new Error('fail')).then(function() {
// not called
}, function(error) {
console.error(error); // Stacktrace
});