ES6 Promise 对象

最后更新:
阅读次数:

基础

  • 异步编程

    • 传统方案:事件 + 回调函数
    • ES6 的新方案:Promise 对象
  • Promise 异步操作有 3 种状态

    • pending: 进行中
    • resolved: 已完成
    • rejected: 已失败
  • Promise 异步操作的状态变化仅限下面两种方式

    • pending –> resolved
    • pending –> rejected

创建一个 Promise 实例

  • Promise 构造函数接收一个函数作为参数,并且这个函数有两个参数,这两个参数是也是两个函数,不过这两个函数由 JavaScript 引擎自动提供,不用自己部署
    • 这两个函数通常表示为 resolvereject,当然也可以用其他名称
let promise = new Promise(function(resolve, reject) {

// ... some code

if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
  • resolve 函数的作用是: 将 Promise 对象的状态从 pending 变为 resolved,并将异步操作成功的结果,作为参数传递出去

  • reject 函数的作用是: 将 Promise 对象的状态从 pending 变为 rejected,并将异步操作报出的错误,作为参数传递出去

  • Promise 新建实例时,构造函数的函数参数会立即执行

let promise = new Promise(function(resolve, reject) {
resolve();
console.log("new Promise");
});

promise.then(function() {
console.log("Resolved.");
});

console.log("Hi!");

// new Promise
// Hi!
// Resolved.

基本方法

  • Promise.prototype.then(onResolved, onRejected): 这个方法在 Promise 实例的状态发生改变时才进行调用

  • then 方法可以接受两个回调函数作为参数

    • 第一个回调函数在状态从 pending 变为 resolved 时才进行回调
    • 第二个回调函数在状态从 pending 变为 rejected 时才进行回调,可选
promise.then(
function(value) {
// success
},
function(error) {
// error
}
);
  • then 方法返回的是一个新的 Promise 实例(注意,不是原来的那个 Promise 实例),因此可以采用链式写法。
promise
.then(
function(value) {
// success
},
function(error) {
// error
}
)
.then(
function(value) {
// success
},
function(error) {
// error
}
);
  • Promise.prototype.catch(): 这个方法仅在 Promise 实例的状态从 pending 变为 rejected 时才进行调用
    • 相当于:Promise.prototype.then(null, onRejected)
    • catch 方法会捕获其前面所有发生的错误
// 最佳写法
promise
.then(function(value) {
// success
})
.catch(function(error) {
// error
});
  • Promise.prototype.finally(): 该方法在 then() 或 catch() 方法执行后执行,返回一个 Promise 对象
    • 作用:避免同样的语句需要在 then() 和 catch() 中各写一次的情况
function delayOneSecond() {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve("hello");
}, 1000);
});
}

delayOneSecond()
.then(value => {
console.log(`then() : ${value}`);
})
.catch(err => {
console.log(`catch() : ${err}`);
})
.finally(value => {
console.log(`finally() : ${value}`);
});

// then() : hello
// finally() : undefined
  • Promise.all(iterable): 当可迭代对象(iterable)的所有元素的状态都是已完成时(resolve 或 reject),该函数返回一个 Promise
let arr = [
123,
new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 666);
})
];

Promise.all(arr).then(data => {
console.log(data); // 一秒之后打印 [123, 666]
});
  • Promise.race(iterable): 当可迭代对象(iterable)有一个元素的状态是已完成时(resolve 或 reject),该函数返回一个 Promise
let arr = [
123,
new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 666);
})
];

Promise.race(arr).then(data => {
console.log(data); // 立即打印 123
});
  • Promise.resolve(value): 返回一个状态是 resolved 并且 resolve 返回值为给定值的 Promise 对象
Promise.resolve("i am resolved").then(data => {
console.log(data);
});
  • Promise.reject(value): 返回一个状态是 rejected 并且 reject 返回值为给定值的 Promise 对象
Promise.reject("i am rejected").catch(data => {
console.log(data);
});

tips: 直接 new Promise() 返回的 Promise 对象的状态是 pending,而使用 Promise.resolve(value)Promise.reject(value) 返回的 Promise 对象的状态是对应的 resolvedrejected

特性

  • Promise 链的一个重要特性是可以给下游 Promise 传递数据
function delayOneSecond() {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve("hello");
}, 1000);
});
}

delayOneSecond()
.then(value => {
return `${value} world`;
})
.then(value => {
console.log(`${value}`);

return `${value}~`;
})
.finally(value => {
console.log(`finally() : ${value}`);
});

// hello world
// finally() : undefined

Promise 的实际应用

  • 封装异步逻辑,方便使用异步函数(async 函数)