参考
Promise
介绍
Promise是 ES6 中新增的一种异步编程的解决方案。从语法上来讲,其是一个构造函数,用于创建一个表示“承诺”的实例。具体见下:
以下假设 ajax 是一个异步操作,接受一个参数作为执行成功的回调函数。ajax 执行过程中可能抛出错误。
new Promise((resolve, reject) => {
try {
ajax((val) => {
resolve(val);
});
} catch (err) {
reject(err);
}
});
其执行流程见下:
- 实例创建后,其状态初始为
pending(进行中),随后参数函数会立即执行。 - 碰到
resolve后,其状态会变为fulfilled(已完成);碰到reject或者抛出错误后,其状态会变为rejected(已拒绝)。 - 继续执行,直到所有代码执行完毕。
- 根据实例状态,执行对应的回调。
这说明,实例的状态最终只可能是fulfilled和rejected两者之一,且没有变回pending的可能。创建Promise实例,就像是抛出一枚硬币,结果要么是正面朝上、要么是反面朝上。
实例方法
// 【then】
// 参数1 - 实例状态改变至fulfilled的回调函数
// 参数2 - 实例状态改变至rejected的回调函数(可选)
// 返回值 - Promise.resolve(执行的回调函数的返回值)
p.then(
(val) => {},
(err) => {}
).then(
(val) => {},
(err) => {}
);
// 【catch】
// err具有冒泡性质,会一直向后传递,直到被捕获,
// 所以在最后写上catch,能保证捕获到错误
p.then((val) => {})
.then((val) => {})
.catch((err) => {});
// 等同于:
p.then((val) => {})
.then((val) => {})
.then((null, err) => {});
// 【finally】
// 无论最后状态如何,都会执行finally中的回调,
// 会自动将值或错误传递下去
p.then((val) => {})
.catch((err) => {})
.finally(() => {});
// 等同于
p.then((val) => {})
.then((null, err) => {})
.then(
(val) => {
// 代码
return val;
},
(err) => {
// 代码
throw err;
}
);
静态方法
// 【all】
// 将多个实例包装成一个新实例,分为2种情况:
// 1.在所有实例的状态都变为fulfilled后,
// 其状态变为fulfilled,返回值为所有实例的返回值组成的数组
// 2.在任一实例的状态变为rejected后,
// 其状态变为rejected,返回值为那个实例的返回值
Promise.all([p1, p2, p3]);
// 【any】
// 将多个实例包装成一个新实例,分为2种情况:
// 1.在任一实例的状态变为fulfilled后,
// 其状态变为fulfilled,返回值为那个实例的返回值
// 2.在所有实例的状态变为rejected后,
// 其状态变为rejected,返回值为所有实例的返回值组成的数组
Promise.any([p1, p2, p3]);
// 【allSettled】
// 将多个实例包装成一个新实例:
// 在所有实例改变状态后,
// 其状态变为fulfilled,返回值为所有实例的返回值组成的数组
Promise.allSettled([p1, p2, p3]);
// 【race】
// 将多个实例包装成一个新实例:
// 在任一实例改变状态后,
// 其状态和返回值都同那个实例
Promise.race([p1, p2, p3]);
// 【resolve】
// 将参数转变为Promise实例,分为4种情况:
// 1.参数是一个Promise实例,
// 则原封不动的返回
// 2.参数是包含then方法的对象,
// 则返回new Promise(obj.then)
// 3.参数是不包含then方法的对象,或者不是对象,
// 则返回new Promise((resolve)=>{resolve(obj)})
// 4.无参数,
// 则返回new Promise((resolve)=>{resolve(undefined)})
Promise.resolve(obj);
// 【reject】
// 将参数转变为Promise实例:
// 返回new Promise((resolve,reject)=>{reject(obj)})
Promise.reject(obj);
应用
可以将图片的加载写成一个Promise,一旦加载完成,Promise的状态就发生变化。具体见下:
const preloadImage = (path) => {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
const getJSON = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
xhr.send();
});
};
getJSON("/posts.json").then(
function (data) {
console.log("Contents:", data);
},
function (err) {
console.error("Error:", err);
}
);
原理
其原理请见此文。
async/await 函数
async/await 函数实际上是利用Promise和Generator函数实现的另一种异步解决方案。
具体请见此文。