Web/06-JavaScript基础:ES6语法/12-Promise的静态方法.md
2021-05-25 20:54:04 +08:00

11 KiB
Raw Blame History

Promise 的常用 API 分类

Promise 的实例方法

实例方法:我们需要先 new 一个 promise 实例对象,然后通过 promise 对象去调用 thencatchfinally方法。这几个方法就是 Promise 的实例方法。

Promise 的自带 API 提供了如下实例方法:

  • promise.then():获取异步任务的正常结果。

  • promise.catch():获取异步任务的异常结果。

  • promise.finaly():异步任务无论成功与否,都会执行。

Promise 的静态方法

静态方法:可以直接通过大写的Promise.xxx调用的方法。这里的xxx就称之为静态方法。

Promise 的自带 API 提供了如下静态方法:

  • Promise.resolve()

  • Promise.reject()

  • Promsie.all():并发处理多个异步任务,所有任务都执行成功,才算成功(走到 resolve只要有一个失败就会走到 reject整体都算失败。

  • Promise.race():并发处理多个异步任务,返回的是第一个执行完成的 promise且状态和第一个任务的状态保持一致。

前面的几篇文章,讲的都是 Promise 的实例方法;今天这篇文章,我们来详细讲一下 Promise 的静态方法

Promise.resolve() 和 Promise.reject()

当我们在定义一个 promise 的过程中,如果涉及到异步操作,那就需要通过new Promise的方式创建一个 Promise 实例。

但有些场景下,我们并没有异步操作,但仍然想调用 promise.then,此时,我们可以用 Promise.resolve() 将其包装成成功的状态。同理,Promise.reject()可以包装成失败的状态。

比如说有的时候promise 里面并不涉及异步操作,我只是单纯地想通过 promise 对象返回一个字符串(有的业务就是有这样的需求),那就可以通过 Promise.reslove('字符串') Promise.reject('字符串') 、这种简写的方式返回。

这两种情况,我们来对比看看。

例 1

function foo(flag) {
    if (flag) {
        return new Promise((resolve) => {
            // 这里可以做异步操作
            resolve('success');
        });

        // return Promise.resolve('success2');
    } else {
        return new Promise((reslove, reject) => {
            // 这里可以做异步操作
            reject('fail');
        });
    }
}

// 执行 reslove 的逻辑
foo(true).then((res) => {
    console.log(res);
});

// 执行 reject 的逻辑
foo(false).catch((err) => {
    console.log(err);
});

例 2见证奇迹的时刻

function foo(flag) {
    if (flag) {
        // Promise的静态方法直接返回字符串
        return Promise.resolve('success');
    } else {
        // Promise的静态方法直接返回字符串
        return Promise.reject('fail');
    }
}

// 执行 reslove 的逻辑
foo(true).then((res) => {
    console.log(res);
});

// 执行 reject 的逻辑
foo(false).catch((err) => {
    console.log(err);
});

例 1 和例 2 的打印结果是一样的。这两段代码的区别在于:例 1 里面可以封装异步任务;例 2 只能单纯的返回一个字符串等变量,不能封装异步任务。

Promise.all()

Promsie.all([p1, p2, p3]):并发处理多个异步任务,所有任务都执行成功,才算成功(才会走到 then只要有一个任务失败就会马上走到 catch整体都算失败。参数里传的是 多个 promise 实例组成的数组。

语法举例

1、异步任务都执行成功时

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise1');
        resolve('promise 1 成功');
    }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise2');
        resolve('promise 2 成功');
    }, 2000);
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise3');
        resolve('promise 3 成功');
    }, 3000);
});

Promise.all([promise1, promise2, promise3])
    .then((res) => {
        // 三个异步任务都执行成功,才会走到这里
        // 这里拿到的 res是三个成功的返回结果组成的数组
        console.log(JSON.stringify(res));
    })
    .catch((err) => {
        // 只要有一个异步任务执行失败,就会马上走到这里
        console.log(err);
    });

打印结果:

// 1秒后
执行 promise1

// 2秒后
执行 promise2

// 3秒后
执行 promise3
["promise 1 成功","promise 2 成功","promise 3 成功"]

2、异步任务有至少一个执行失败时

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise1');
        resolve('promise 1 成功');
    }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise2');
        // 这里通过 reject() 的方式,表示任务执行失败
        reject('promise 2 失败');
    }, 2000);
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise3');
        resolve('promise 3 成功');
    }, 3000);
});

Promise.all([promise1, promise2, promise3])
    .then((res) => {
        // 三个异步任务都执行成功,才会走到这里
        console.log('走到 then:' + JSON.stringify(res));
    })
    .catch((err) => {
        // 只要有一个异步任务执行失败,就会马上走到这里
        console.log('走到 catch:' + err);
    });

打印结果:

// 1秒后
执行 promise1

// 2秒后
执行 promise2
走到 catch:promise 2 失败

// 3秒后
执行 promise3

可以看到,当 promise2 执行失败之后,马上就走到了 catch而且 promise3 里的 resolve 并没有执行。

Promise.all()举例:图片上传

比如说,现在有一个图片上传的接口,每次请求接口时只能上传一张图片。需求是:当用户连续上传完三张图片(甚至是更多图片)之后,给用户一个“上传成功”的提示。这个时候,我们就可以使用Promsie.all()

Promise.race()

Promise.race([p1, p2, p3]):并发处理多个异步任务,返回的是第一个执行完成的 promise且状态和第一个任务的状态保持一致。参数里传的是多个 promise 实例组成的数组。

上面这句话,第一次读时,可能很绕口。我说的再通俗一点:在多个同时执行的异步任务中,先找出哪个异步任务最先执行完成(无论是走到 resolve还是走到 reject都算执行完成。然后整体的状态跟这个任务保持一致。如果这个任务执行成功那整体就算成功走到 then如果这个任务执行失败那整体就算失败走到 catch

race的中文翻译,可以理解为“竞赛”。意思是,谁先抢到名额,就认定谁了。无论这个人最终的结局是成功或者失败,整体的结局,都以这个人的结局为准。

我刚开始学 Promise.race()的时候,误以为它的含义是“只要有一个异步执行成功,整体就算成功(走到 then所有任务都执行失败整体才算失败走到 catch”。现在想来真是大错特错过于懵懂。

我们来看看各种场景的打印结果,便能让你擦干泪水。

语法举例

场景 1、所有任务都执行成功时

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise1');
        resolve('promise 1 成功');
    }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise2');
        resolve('promise 2 成功');
    }, 2000);
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise3');
        resolve('promise 3 成功');
    }, 3000);
});

Promise.race([promise1, promise2, promise3])
    .then((res) => {
        // 只要有一个异步任务执行成功,就会走到这里
        // 这里拿到的 res是第一个成功的 promise 返回的结果,不是数组
        console.log(JSON.stringify(res));
    })
    .catch((err) => {
        // 所有异步任务异步都执行失败,才会走到这里
        console.log(err);
    });

打印结果:

// 1秒后
执行 promise1
"promise 1 成功"

// 2秒后
执行 promise2

// 3秒后
执行 promise3

场景 2、第一个任务成功、第二个任务失败时

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise1');
        resolve('promise 1 成功');
    }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise2');
        // 第二个任务执行失败时
        reject('promise 2 失败');
    }, 2000);
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise3');
        resolve('promise 3 成功');
    }, 3000);
});

Promise.race([promise1, promise2, promise3])
    .then((res) => {
        // 第一个完成的任务,如果执行成功,就会走到这里
        console.log('走到then:' + res);
    })
    .catch((err) => {
        // 第一个完成的任务,如果执行失败,就会走到这里
        console.log('走到catch:' + err);
    });

打印结果:

// 1秒后
执行 promise1
走到then:promise 1 成功

// 2秒后
执行 promise2

// 3秒后
执行 promise3

可以看出,场景 2 的打印结果和场景 1 的打印结果,是一样的。因为最新执行完成的任务,是成功的,所以整体会马上走到 then且整体就算成功。

场景 3、第一个任务失败、第二个任务成功时

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise1');
        // 第一个任务执行失败时
        reject('promise 1 失败');
    }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise2');
        resolve('promise 2 成功');
    }, 2000);
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('执行 promise3');
        resolve('promise 3 成功');
    }, 3000);
});

Promise.race([promise1, promise2, promise3])
    .then((res) => {
        // 第一个完成的任务,如果执行成功,就会走到这里
        console.log('走到then:' + res);
    })
    .catch((err) => {
        // 第一个完成的任务,如果执行失败,就会走到这里
        console.log('走到catch:' + err);
    });

打印结果:

// 1秒后
执行 promise1
走到catchpromise 1 失败

// 2秒后
执行 promise2

// 3秒后
执行 promise3

看清楚了没?场景 3 的最终打印结果,是走到了 catch任务 2 和任务 3 里的 resolve并没有继续执行。

场景 3 的代码,一定好好好理解。

我的公众号

想学习更多技能?不妨关注我的微信公众号:千古壹号

扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: