前端那些事

vuePress-theme-reco chenpeng    2020 - 2021
前端那些事 前端那些事

Choose mode

  • dark
  • auto
  • light
首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
author-avatar

chenpeng

85

Article

25

Tag

首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
  • ES6-异步

    • Generator生成器函数
    • Promise
    • async与await

Promise

vuePress-theme-reco chenpeng    2020 - 2021

Promise

chenpeng 2020-11-30 ES6异步

# 1.概念

Promise 意为“承诺”,表示将来会执行的操作,代表异步操作

共有三种状态:

  1. pending:进行中
  2. fulfilled:已成功
  3. rejected:已失败

特点:

  1. 只有异步操作可以决定当前处于的状态,其他任何操作都无法改变这个状态
  2. 一旦状态改变,就不会再变。状态改变的过程只可能是:从 pending 变为 fulfilled 和从 pending 变为 rejected。如果状态发生上述改变后,就不会再发生改变,此时就称为 resolved(已定型)

# 2.基本用法

创建 Promise

const p = new Promise((resolve, reject) => {
    if(success){
        resolve(value);
    }else{
        reject(error);
    }
})
1
2
3
4
5
6
7

该构造函数接收两个参数:resolve 和 reject,当异步操作执行成功后,将异步操作的结果传入 resolve 函数并执行,此时状态从 pending 变为 fulfilled;当异步操作执行失败后,将异步操作的错误传入 reject 函数并执行,此时状态从 pending 变为 rejected

接下来通过 then 方法,分别指定 resolve 和 reject 的回调函数

p.then(value => {
	// success
}, error => {
	// failure
})
1
2
3
4
5

then 方法接收两个回调函数作为参数,第一个回调函数在 fulfilled 状态时调用,第二个回调函数在 rejected 状态时调用,其中第二个参数是可选的

Promise 新建之后就会立即执行

new Promise(resolve => {
    resolve(1);
    console.log(2)
}).then(value => {
    console.log(value);
})
// 2
// 1
1
2
3
4
5
6
7
8

上述代码中,Promise 新建后会立即执行,所以首先输出2,然后 then 方法指定的回调函数,将在当前脚本所有同步代码执行完成后才会执行,所以最后输出1

注意:resolve 或 reject 并不会终结 Promise 函数的执行

一般来说,调用 resolve 或 reject 后,Promise 的使命就完成了,后续操作应该放在 then 或 catch 方法里面,而不应该直接写在 resolve 或 reject 后面,所以最好在它们前面加上 return 语句,这样就不会有意外

new Promise(resolve => {
    return resolve(1);
    // 后面的语句不会再执行
    console.log(2)
})
1
2
3
4
5

# 3.Promise 的方法

# 3.1 Promise.resolve(value)

返回一个以给定值解析的 Promise 对象

如果这个值是一个 promise,则直接返回这个 promise

const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
p2.then(value => {
    console.log(value); // 1
})
1
2
3
4
5

如果这个值是一个 thenable 对象(即带有 then 方法),返回的 promise 会跟随这个 thenable 对象,采用它的最终状态

const thenable = {
    then(resolve, reject){
        resolve('done')
    }
};
const p2 = Promise.resolve(thenable);
p2.then(value => {
    console.log(value); // done
})
1
2
3
4
5
6
7
8
9

如果这个值是一个普通对象,则将这个值作为最终结果并返回一个新的 promise

如果这个值为空,则返回一个 resolved 状态的 promise

# 3.2 Promise.reject(reason)

返回一个带有拒绝原因的 Promise 对象,传入的参数会作为 reject 函数的原因,不会因为传入的参数改变而改变

# 3.3 Promise.all(iterable)

返回一个 Promise 实例,iterable 必须是一个可迭代对象,如 Array 或 String

如果传入的参数不是 Promise 实例,则会先调用 Promise.resolve 将其转换为 Promise 实例

如果传入的参数是一个空的可迭代对象,则返回一个**已完成(already resolved)**状态的 Promise

const p = Promise.all([]);
console.log(p); // Promise {<fulfilled>: Array(0)}
1
2

如果传入的参数非空,则返回一个**异步完成(asynchronously resolved)**状态的 Promise

const p = Promise.all([Promise.resolve(1), Promise.resolve(2)]);
console.log(p); // Promise {<pending>}
1
2

如果传入的参数中任意一个 promise 返回失败时,整体返回失败,返回的错误信息是第一个失败的 promise 结果

const p = Promise.all([Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)]);
p.then(value => {
    console.log(value);
}, reason => {
    console.log(reason);
})
// error
1
2
3
4
5
6
7

# 3.4 Promise.race(iterable)

返回一个新的 Promise 实例,iterable 必须是一个可迭代对象,如 Array 或 String

如果传入的参数不是 Promise 实例,则会先调用 Promise.resolve 将其转换为 Promise 实例

race 有“赛跑”的意思,因此返回的新实例的状态,是跟随参数中最先改变状态的那个实例

const p1 = new Promise(resolve => {
    setTimeout(resolve, 100, 'p1');
});
const p2 = new Promise(resolve => {
    setTimeout(resolve, 50, 'p2');
});
Promise.race([p1, p2]).then(value => {
    console.log(value);
})
// p2
1
2
3
4
5
6
7
8
9
10

# 3.5 Promise.allSettled(iterable)

返回一个对象数组,每个对象表示对应的 promise 结果

const p = Promise.allSettled([Promise.resolve(1), Promise.reject('error')]);
p.then(value => {
    console.log(value);
})
/*
0: {status: "fulfilled", value: 1}
1: {status: "rejected", reason: "error"}
*/
1
2
3
4
5
6
7
8

# 4.Promise 原型方法

# 4.1 Promise.prototype.then()

Promise 的实例具有 then 方法,主要作用是为 Promise 实例发生状态改变时添加回调函数。它接收两个回调函数作为参数,第一个参数是 fulfilled 状态时的回调函数;第二个参数是rejected 状态时的回调函数,可不传入,并且该方法返回一个新的 Promise 对象

p.then(onFulfilled, onRejected);

p.then(value => {
    // fulfillment
}, reason => {
    // rejection
});
1
2
3
4
5
6
7

# 4.2 Promise.prototype.catch()

返回一个 Promise,并且处理拒绝的情况。它的行为与调用 Promise.prototype.then(undefined, onRejected)相同,该方法也返回一个新的 Promise 对象

p.catch(reason => {
    
})
1
2
3

推荐使用 catch 方法,而不是在 then 方法中定义 rejected 状态的回调函数,因为使用 catch 方法还可以捕获 then 方法执行中产生的错误

Promise.prototype.then() 与 Promise.prototype.catch() 方法都返回 Promise 对象,所以它们可以被链式调用

# 4.3 Promise.prototype.finally()

返回一个 Promsie,指在上一轮 promise 运行结束后,无论fulfilled还是 rejected,都会执行指定的回调函数。该方法适合无论结果如何都要进行的操作,例如清除数据

p.finally(onFinally);

p.finally(function() {

})
1
2
3
4
5