Promise 详解

1、Promise 的含义

初识Promise,要从多方面去理解,可以直接百度Promise,只看别人博客的前面的含义介绍,先不深入看别人的博客,基本可以了解到:

  • promise原意:诺言; 许诺; 承诺;预示。
  • Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。链接描述
  • Promises 是一种 JavaScript 中处理异步代码的方法,其实 Promises 已经存在多年,但是直到 ES2015 (ES6)才被标准化和引入,现在它们已经在 ES2017(ES8) 中被 async(异步) 函数所取代和扩展,可见发展之快。链接描述
  • 一个 Promise 就是一个对象,它代表了一个异步操作的最终完成或者失败。链接描述
  • Promise对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。
  • ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
  • Async functions(异步函数) 使用 promises API 作为构建块,因此理解 Promises 是必须的,即使在较新的代码中,你可能会使用 async(异步) 函数而不是promises 。链接描述

2、同步、异步、回调函数相关概念

  • JavaScript的执行环境是单线程。所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会阻塞其他任务。这个任务可称为主线程。但实际上还有其他线程,如事件触发线程、ajax请求线程等。
  • 同步模式,即上述所说的单线程模式,一次只能执行一个任务,函数调用后需等到函数执行结束,返回执行的结果,才能进行下一个任务。如果这个任务执行的时间较长,就会导致线程阻塞。
    /* 例2.1 */
    var x = true;
    while(x);
    console.log("don't carry out");    //不会执行
    上面的例子即同步模式,其中的while是一个死循环,它会阻塞进程,因此第三句console不会执行。
    同步模式比较简单,也较容易编写。但问题也显而易见,如果请求的时间较长,而阻塞了后面代码的执行,
    体验是很不好的。因此对于一些耗时的操作,异步模式则是更好的选择。
  • 异步模式,即与同步模式相反,可以一起执行多个任务,函数调用后不会立即返回执行的结果,如果任务A需要等待,可先执行任务B,等到任务A结果返回后再继续回调。最常见的异步模式就数定时器了,我们来看看以下的例子。
    /* 例2.2 */
    setTimeout(function() {
        console.log('taskA, asynchronous');
    }, 0);
    console.log('taskB, synchronize');
    //while(true);

    -------ouput-------
    taskB, synchronize
    taskA, asynchronous
    我们可以看到,定时器延时的时间明明为0,但taskA还是晚于taskB执行。
    这是为什么呢?由于定时器是异步的,异步任务会在当前脚本的所有同步 任务执行完才会执行。
    如果同步代码中含有死循环,即将上例的注释去掉,那么这个异步任务就不会执行,因为同步任务阻塞了进程。

  • 回调函数,提起异步,就不得不谈谈回调函数了。上例中,setTimeout里的function便是回调函数。可以简单理解为:(执行完)回(来)调(用)的函数。
    **WikiPedia对于callback的定义。**
    In computer programming, a callback is a piece of executable code that is passed as 
    an argument to other code, which is expected to call back (execute) the argument 
    at some convenient time.
    可以看出,回调函数是一段可执行的代码段,它以「参数」的形式传递给其他代码,
    在其合适的时间执行这段(回调函数)的代码。
    **WikiPedia还定义**
    The invocation may be immediate as in a synchronous callback, 
    or it might happen at a later time as in an asynchronous callback.
    也就是说,回调函数不仅可以用于异步调用,一般同步的场景也可以用回调。
    在同步调用下,回调函数一般是最后执行的。而异步调用下,可能一段时间后执行或不执行(未达到执行的条件)。

3、Promise 的特点和基本用法

promise对象有两个特点:

  • 对象的状态不受外界影响,pending(进行中)、fulfiled(已完成)、rejected(已失败)
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果,状态改变只有两种可能,称为(resolved)

基本用法:

es6规定,Promise对象是一个构造函数,用来生成Promise实例。
扩展构造函数回顾:特殊方法,创建对象时初始化对象,为对象成员变量赋初始值,与new一起使用。
一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。
var promise = new promise(function(resove, reject){
  // ... some code
  if (/*异步成功*/){
    resove(value);
  } else{
    reject(error);。
  }
});

简单例子1

例子用到了箭头函数,写法很容易理解,可参考另一篇文章


    let p= new Promise((resolve, reject)=>{
        let a1='成功传出去的对象';
        let a2='失败传出去的对象';
        var timer = setTimeout(function () {
                     console.log('after resolve');
                    resolve(a1);
                    reject(a2);
                    console.log('after error');
                }, 1000);
    });
    p.then(value=>{
        console.log(value);
    },error=>{
        console.log('.then的第二个参数');
        console.log(error)
    });
    p.catch(error=>{
        console.log('.catch');
        console.log(error);
    });
    

上面例子的输出效果,出现的第一行是Promise{<pending>},
然后再次输入p 按回车执行打印出来p是这样Promise{<resolved>}
然后点开看 可以看到控制台提示promiseStatus :resolved 说明promise的状态已经成为了resolved
《Promise 详解》
上面例子把resolve(a1)去掉,结果如下:
《Promise 详解》

4、解读promise中唯一的参数、resolve参数、reject参数、then()、catch()方法的意义

参考上面例子1

  • let p = new Promise(参数1),创造一个实例时,接受一个函数作为参数1;
  • 参数1,作为函数,也接受两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。注意:这两个函数的作用就是改变Promise对象的状态,一个是成功,一个是失败,一旦调用了其中一个,状态就不可改变和逆转;
  • Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数,即使用p.then()来进一步的操作,注意:then()可以接受两个参数,这两个参数也是函数,第一个表示成功的操作,就是调用了resolve(a1)后会进入,第二个表示失败的操作,就是调用了reject(a1)后会进入,但第二个可以省略;
  • p.catch和.then()第二个参数的效果是一样,都会进入;
  • 例子1的resolve(a1)和reject(a2)同时存在时,只有在前面的有用,可注释第一个看失败的效果;
  • 例子中的resolve,reject只是个名字,其实可以随便改,不建议改;
  • 例子中p.then(value=>{console.log(value)},这里面的value也只是个名字,其实可以随便改,不建议改;注意:value就是上面resolve(a1)中传出来的a1,a1可以是任何对象,a2也是相同的道理。
    原文作者:老屋
    原文地址: https://segmentfault.com/a/1190000019340298
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞