Promise初窥

什么是Promise?

⚠️笔者默认读到这篇文章的人有JavaScript基础运行原理的相关知识,如果对JavaScript运行原理不甚了解,可以先简单阅读下这篇文章「硬核JS」一次搞懂JS运行机制。后续笔者也会写一篇较为基础的JavaScript运行机制浅析。

在JavaScript执行的过程中,我们会遇到很多异步任务。因为这些任务不在主线程上进行,而是由相应的异步处理模块处理,我们为了能够获得这个异步任务的执行结果,往往会注册一个回调函数给异步任务,在异步任务完成时调用回调函数,将执行结果作为参数传回。

Promise正是异步编程的一类通用解决方案。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 它最为称道的优点就是通过支持链式调用,解决繁冗的「回调地狱」问题。

如何使用Promise?

  1. 如何创建一个 new Promise

    1
    2
    3
    4
    5
    
    const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('好耶,是大冒险时间!');
        }, 300);
    });
    

    创建一个实例化的promise对象非常简单,只需要使用new Promise来进行构造。一般来说Promise构造函数接收一个函数作为其参数,而该函数的两个参数分别是resolvereject,当函数体内的异步操作成功执行就调用resovle,失败就调用reject

  2. 如何使用 Promise.prototype.then

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('好耶,是大冒险时间!');
        }, 300);
    });
    
    myPromise
        .then((value)=>{
            console.log(value)
        })
    //好耶,是大冒险时间!
    

    实例方法then()返回一个promise对象,它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

    听起来有些绕口,实际上就是myPromise.then( success , fail )

    如果还是觉得有些难以理解的话,那么这张图可能会为你解惑⬇️

    result◎ 试着运行myPromise与myPromise.then( ... )

    myPromise是一个promise对象,fulfilled代表了异步操作处于完成状态并调用了设定的resolve函数,PromiseResult为值(value)。到此为止,如果我们不补充then()方法的话,我们并不能知道myPromise的执行结果(诚然在简单情况下,比如图例中,你大可以自己打印一下整个对象,然后寻找需要的PromiseResult),而补充了then(...)方法作为回调函数,在输出端,我们可以直接获取到想要的值,同时它返回的也是一个promise对象,可以供后续进行进一步的链式操作。

  3. 如何使用 Promise.all

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    const promise1 = Promise.resolve(3);
    const promise2 = 42;
    const promise3 = new Promise((resolve, reject) => {
        setTimeout(resolve, 100, 'foo');
    });
    
    Promise.all([promise1, promise2, promise3]).then((values) => {
        console.log(values);
    });
    // [3, 42, 'foo']
    

    Promise.all()方法可以一次性接收多个promise对象,但是只会返回一个Promise实例,不过存在两种返回情况:

    1. 所传入的promise均正常执行并返回,resolve 的回调结果是一个数组,它包含所有的传入迭代参数对象的值(也包括非 promise 值)。
    2. 如果传入的promise中有一个失败(rejected),Promise.all就会返回第一个失败的结果,不论其他promise是否完成。
  4. 如何使用 Promise.race

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    const promise1 = new Promise((resolve, reject) => {
        setTimeout(resolve, 500, '这个500就是又慢又逊啦');
    });
    
    const promise2 = new Promise((resolve, reject) => {
        setTimeout(resolve, 100, '快人一步,懂?');
    });
    
    Promise.race([promise1, promise2]).then((value) => {
        console.log(value);
    });
    // 快人一步,懂?
    

    Promise.race()方法可以一次性接收多个promise对象,同样只会返回一个Promise实例,不过这种返回「人如其名」,是一场「竞赛」:

    1. 所传入的promise对象,只要有一个状态发生改变(不论成功resolve/失败reject),Promise.race()会直接返回第一个完成的promise