• 浅谈ES6的promise


    promise对象的两个特点:
    1. 对象的状态不受外界影响。promise对象有三种状态:Pending(进行中),Resolved(已完成,也叫fulfilled)和rejected(已失败)。
    2. 一旦状态改变,就不会再变。
    构造promise函数:
    var promise = new Promise(function(resolve, reject){
         if (/* 异步操作成功*/) {
              resolve(value);
         } else {
              reject(error);
         }
    });
    其中resolve函数的作用:将promise的状态从“未完成”变成“成功”,pending -> resolved
    reject函数作用:将promise状态从pending -> rejected
     
    .then的使用
    1) 构造promise函数后,可以使用.then来指定对应的resolve和reject函数。
      promise.then(function(value){
           // success
      }, function(error){
           // failure
      })
     
    2)resolve的执行顺序问题
      new Promise((resolve, reject) => {
           resolve(1);
           console.log(2);
      }).then(r => {
        console.log(r);
      });
    以上代码运行结果为:先打印2,再打印1。这是因为resolve是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
      new Promise((resolve, reject) => {
             reject('error');
             console.log(2);
      }).catch(r => {
             console.log(r);
      });
    同理,对于reject也是一样,运行结果为先打印2,再打印error
     
    这里面牵涉到一个事件循环的原理。为了更好的理解,插播一下事件循环的原理:
    众所周知,JS是单线程。为了解决JS单线程漫长等待的问题,产生了两种JS的执行方式,即同步执行和异步执行。同步执行是指,一个任务结束了然后再执行下一个任务,异步执行是指CPU跳过等待时间长的任务,先去执行后面的任务。
    异步执行的机制实现如下:
    1 所有任务都在主线程上执行,形成一个执行栈。
    2 主线程之外,有一个任务队列。系统会把异步任务防在任务队列里,然后继续去执行后续的任务。
    3 执行栈中的任务执行完毕,系统就会去任务队列里读取异步任务,如果此时异步任务已经结束了等待状态,就会从任务队列进入执行栈。
    4 主线程不断重复以上过程,就是事件循环的过程。
    5 定时器setTimeout和setInterval也会将事件插入到任务队列中,也就是必须要等到当前代码执行执行完,主线程才会去执行指定的回调函数。所以没有办法保证,回调函数一定会在指定的时间内执行。
    6 DOM的变动,通常不会立即执行,而是16毫秒执行一次,使用requestAnimationFrame()的效果要好于setTimeout()。
     
    3)链式的then
    采用链式的then,可以指定一组按照次序调用的回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入下一个回调函数中。
     
    .catch的使用
    Promise.prototype.catch方法是.then(null, reject)的别名,用于指定发生错误时的回调函数。主要有两个用户:在异步操作抛出错误状态变成rejected的时候调用.catch指定的回调函数,在then方法指定的回调函数执行发生错误时会被.catch方法捕获。
     
    使用.catch捕获错误如下:
    var promise = new Promise(function(resolve, reject) {
      throw new Error('test');
    });
    promise.catch(function(error) {
      console.log(error);
    });
    运行结果为:
    Error: test error
        at <anonymous>:2:9
        at Promise (<anonymous>)
        at <anonymous>:1:15
    等同于:
    var promise = new Promise(function(resolve, reject) {
      reject(new Error('test'));
    });
    promise.catch(function(error) {
      console.log(error);
    });
     
    promise.all()
    用于将多个promise实例,包装成一个新的promise实例。
    var p = Promise.all([p1, p2, p3]);
    P的状态由p1,p2,p3决定:
    1 p1,p2,p3的状态都变成fulfilled,p的状态才会变成fulfilled。
    2 只要有一个返回的状态是rejected,那么p的状态就变成rejected,且第一个被rejected的实例的返回值,会传递给p的回调函数。注意,如果实例定义了自己的catch方法,则不会触发promise.all()的catch方法。
    var p1 = new Promise(function (resolve) {
      setTimeout(function () {
      resolve("Hello");
      }, 3000);
    });
    var p2 = new Promise(function (resolve) {
      setTimeout(function () {
      resolve("World");
      }, 1000);
    });
    Promise.all([p1, p2]).then(function (result) {
      console.log(result);
    });
    上述运行结果为: ["Hello", "World"],因为Promise.all方法会按照数组里面的顺序返回结果。
     
    promise.race()
    var p = Promise.race([p1, p2, p3]);
    也是将多个promise实例包装成一个新的promise实例。与上面的方法不同的是,只要p1p2p3有一个实例率先改变了状态,p的状态也跟着改变,而且率先改变的promise的返回值,会传给P的回调函数。
  • 相关阅读:
    Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    Centos安装openjdk
    centos7安装nodejs
    Linux服务器集群性能监控之Performance Co-Pilot(PCP)部署
    asp.net(c#)网页跳转七种方法小结
    C# 获取文件名及扩展名
    C#中的 具名参数 和 可选参数
    数据契约(DataContract)
    用LINQ在集合中查询特定对象
    jQuery中append、insertBefore、after与insertAfter方法注意事项
  • 原文地址:https://www.cnblogs.com/xmll/p/7275789.html
Copyright © 2020-2023  润新知