JavaScript Promise | 菜鸟教程
特点
Promise 对象代表一个异步操作,对象的状态不受外界影响,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败);只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态;
一旦状态改变就不会再变,Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled,从 pending 变为 rejected;如果改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果;这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的;
构造函数 Promise 必须接收一个函数(handle)作为参数,函数又包含 resolve 和 reject ;
then 、catch 支持链式调用;
缺点Promise 无法取消:一旦新建就会执行,无法中途取消;
如果不设置回调函数,Promise 内部抛出的错误不会反应到外部;
当处于 pendding 状态时,无法知道目前进展到哪一个阶段;
最初状态:pending,等待中,此时promise的结果为 undefined;
当 resolve(value) 调用时,达到最终状态之一:fulfilled,(成功的)完成,此时可以获取结果value
当 reject(error) 调用时,达到最终状态之一:rejected,失败,此时可以获取错误信息 error
Promise.all()
Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的.then操作(等待机制),数组中 Promise 实例的顺序,就是最终结果的顺序
Promise.race()
Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一 步的.then 操作(赛跑机制),有一个promise异步操作执行完毕时,then方法中的结果时最先获取数据的结果
Promise 构造函数是 JavaScript 中用于创建 Promise 对象的内置构造函数。
Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。
起始函数执行成功时,它应该调用 resolve 函数并传递成功的结果。当起始函数执行失败时,它应该调用 reject 函数并传递失败的原因。
Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('success');
} else {
reject('error');
}
}, 1000);
});
promise.then(result => {
console.log(result);
}).catch(error => {
console.log(error);
});
在上面的例子中,我们使用 Promise 构造函数创建了一个 Promise 对象,并使用 setTimeout 模拟了一个异步操作。如果异步操作成功,则调用 resolve 函数并传递成功的结果;如果异步操作失败,则调用 reject 函数并传递失败的原因。然后我们使用 then 方法处理 Promise 成功状态的回调函数,使用 catch 方法处理 Promise 失败状态的回调函数。
这段程序会直接输出 error 或 success。
resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的
new Promise(function (resolve, reject) {
var a = 0;
var b = 1;
if (b == 0) reject("Divide zero");
else resolve(a / b);
}).then(function (value) {
console.log("a / b = " + value);
}).catch(function (err) {
console.log(err);
}).finally(function () {
console.log("End");
});
//结果 a / b = 0 End
Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列:
new Promise(function (resolve, reject) {
console.log(1111);
resolve(2222);
}).then(function (value) {
console.log(value);
return 3333;
}).then(function (value) {
console.log(value);
throw "An error";
}).catch(function (err) {
console.log(err);
});
resolve() 中可以放置一个参数用于向下一个 then 传递一个值,then 中的函数也可以返回一个值传递给 then。但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作,这一点从刚才的计时器的例子中可以看出来。
reject() 参数中一般会传递一个异常给之后的 catch 函数用于处理异常。
但是请注意以下两点:
异步函数(async function)是 ECMAScript 2017 (ECMA-262) 标准的规范,几乎被所有浏览器所支持,除了 Internet Explorer。
在 Promise 中我们编写过一个 Promise 函数:
function print(delay, message) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(message);
resolve();
}, delay);
});
}
然后用不同的时间间隔输出了三行文
print(1000, "First").then(function () {
return print(4000, "Second");
}).then(function () {
print(3000, "Third");
});
我们可以将这段代码变得更好看
async function asyncFunc() {
await print(1000, "First");
await print(4000, "Second");
await print(3000, "Third");
}
asyncFunc();
处理异常的机制将用 try-catch 块实现:
async function asyncFunc() {
try {
await new Promise(function (resolve, reject) {
throw "Some error"; // 或者 reject("Some error")
});
} catch (err) {
console.log(err);
// 会输出 Some error
}
}
asyncFunc();
如果 Promise 有一个正常的返回值,await 语句也会返回它:
async function asyncFunc() {
let value = await new Promise(
function (resolve, reject) {
resolve("Return value");
}
);
console.log(value);
}
asyncFunc();//Return value