资讯专栏INFORMATION COLUMN

ES6的Promise:要优雅,也要浪漫

weizx / 1875人阅读

摘要:就算改变已经发生了,即使再对对象添加回调函数,也会立即得到这个结果。方法接收个参数,第一个参数是状态的回调函数,第二个参数可选是状态的回调函数。简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

在ECMAScript 6标准中,Promise被正式列为规范,Promise,字面意思就是“许诺,承诺”,嘿,听着是不是很浪漫的说?我们来探究一下这个浪漫的Promise对象到底是如何许下承诺,又是如何兑现TA的诺言的。

1.许下一个Promise(承诺)

下面我们将通过一些简单的例子,来一步一步的探究Promise的含义,更重要的是,用心体会Ta的优雅和浪漫(PS:让程序猿体会浪漫,是不是难为大家了)

在ES6标准中被定义为一个构造函数,那好我们就先new一个对象出来看看。

var promise = new Promise(function(resolve,reject){
   //一个异步操作
    setTimeout(function(){
        let foo = 1;
        console.log("执行完成");
        resolve(foo);
    }, 2000);
});

上面的代码就可以看作是Promise给我们许下了一个承诺,不过,这特么到底是个啥意思呢?
构造函数Promise接收一个回调函数做参数,同时这个回调函数又接受2个function做参数,本例中分别起名叫resolvereject,分别代表异步操作执行成功后的操作,和异步操作执行失败后的操作
ES6标准中规定一个 Promise的当前状态必须为以下三种状态中的一种:

进行中(Pending

已完成(ResolvedFulfilled

已失败(Rejected

下表简单总结了三种状态所代表的含义:

名称 含义 满足条件
Pending 进行中 操作正在执行,可以切换为Resolve或Rejected状态
Resolved 已完成 必须拥有一个不可变的终值,且不可以切换到其他状态
Rejected 已失败 必须拥有一个不可变的终值,且不可以切换到其他状态

当Promise的状态由pending状态,通过resolve函数改变为resolved,或者通过reject函数改变为rejected后,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,即使再对Promise对象添加回调函数,也会立即得到这个结果。

2.兑现你的承诺

最重要的不是看Ta怎么说,重要的是要看Ta怎么做。既然许下了承诺,就必须要兑现承诺。
下面就要介绍Promise.prototype.then()方法,来访问其当前值、终值和据因。它的作用是为Promise实例添加状态改变时的回调函数then方法接收2个参数,第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。
废话不多说直接上示例代码:

function foo (a){
  var promise = new Promise(function(resolve,reject){
      setTimeout(function(){
          if(a > 0){
            resolve(a);
          }else {
            reject(a);
          }
      }, 2000);
  });
  return promise;
}

foo(1).then(function(a){
  console.log("success",a+1);
},function(a){
  console.log("error",a);
});

上面的代码中,简单设定一个定时任务模拟异步操作,当a>0时,认为操作成功,则在then方法中执行第一个回调函数,输出success;当传入的值 a<0时,就被认为操失败,则then方法执行第二个回调函数,输出error。看到这里,我们可能会感觉到Promise 和我们之前用的回调函数有点相似,但是貌似Promise是用同步的写法来处理异步的操作。简单来讲,Promise就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
我们了解了以上的基本原理,以后碰到需要传递多个callback的情况的时候,就可以使用Promise实现链式调用,从而避免陷入回调地狱中。
示例代码:

function foo(a) {
  ++a;
  console.log(a);
  var promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (a > 0) {
        resolve(a);
      } else {
        reject(a);
      }
    }, 2000);
  });
  return promise;
}
function foo2(a) {
  ++a;
  console.log(a);
  var promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (a > 1) {
        resolve(a);
      } else {
        reject(a);
      }
    }, 2000);
  });
  return promise;
}
function foo3(a) {
  ++a;
  console.log(a);
  var promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (a > 2) {
        resolve(a);
      } else {
        reject(a);
      }
    }, 2000);
  });
  return promise;
}
function foo4(a) {
  ++a;
  console.log(a);
  var promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (a > 3) {
        resolve(a);
      } else {
        reject(a);
      }
    }, 2000);
  });
  return promise;
}

//链式调用各个处理函数
foo(1).then(function (a) {
  return foo2(a);
})
.then(function (a) {
  return foo3(a);
})
.then(function (a) {
  return foo4(a);
})
3.承诺兑现不了咋办

并不是所有的承诺都会被兑现,就好像小时候父母都说帮我们存压岁钱以后还给我们一样。Promise中也是如此,总会有我们意想不到的差错发生导致无法按照预期的函数进行执行,
所以Promise提供了一个名为catch的方法帮我们解决这个问题。
Promise.prototype.catch()方法有2个作用,第一个作用,就是和then方法中的第二个参数作用相同,就是当状态切换成rejected时执行相应的操作,例如第一个例子中换个写法:

foo(1)
.then(function(a){
  console.log("success",a+1);
})
.catch(function(a){
  console.log("error",a);
});

作用和原来完全一致。
第二个作用就是在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。

4.玩儿了命也要兑现承诺

要是你在生活中真遇到一个肯为你玩儿命的人。。。。。
关我毛事,劳资单身狗,秀恩爱的请移步他处。。。。。
Promise中提供了Promise.all方法,注意all方法是直接定义在Promise上的而不是原型链中。主要作用就是提供了并行执行异步操作的能力,让程序玩了命的跑起来。

var promise = Promise.all([p1, p2, p3]).then(function (p) {
  console.log(p);
});

Promise.all会将多个Promise的实例,包装成一个新的Promise实例,然后传递给后面的then方法。

Promise.all方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例

兼容性

说了这么多,哇塞这么优雅的特性一定要用起来啊,但是在激动之余,毕竟Promise是ES6标准中的新增对象,所以还是得冷静下来检查一下Promise对象的兼容性如何,

通过在can I use...网站上获取到的统计数据看来,Promise对象的兼容性不是很好,目前只有在比较新的主流浏览器中才得到全面支持,而且我们注意到微软的所有IE浏览器均不支持该对象,只有在win10中的Edge浏览器中才获得支持。看来我们在准备使用Promise的时候,还是要视自己的实际开发环境而定。

关于ES6的其他特性的最新支持情况,请点击这里

总结

Promise作为ES6标准中一个比较新鲜的特性,还有其他方法这里没有讲到,比如resolve,reject,race等,受限于水平与时间精力,今天暂时先写这么多,以后有时间再继续补充,对于文中的错误和不足,欢迎大家指出讨论,共同学习进步(虽然我不一定看。。。。逃。。)

附:在GitHub上阅读请点击

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80784.html

相关文章

  • 「大概可能也许是」目前最好 JavaScript 异步方案 async/await

    摘要:使用时也要注意范围和层级。服务端配置服务端使用,最简单的方式是通过。云引擎是推出的服务器端运行环境,支持和环境,功能强大而且目前免费,结合,使原本复杂的开发工作变得简单高效。目前也支持和海外节点,轻松满足你的业务需求。 构建一个应用程序总是会面对异步调用,不论是在 Web 前端界面,还是 Node.js 服务端都是如此,JavaScript 里面处理异步调用一直是非常恶心的一件事情。以...

    Scorpion 评论0 收藏0
  • 极客爱情: 情人节礼物大作战

    摘要:故而总结如下编成的代码浪漫的环境亲手制作的礼物注意请将下面的程序员的情人节礼物换成语言。言归正传程序员的情人节礼物入门之材料构思情人节礼物之设备展示想着在这个移动盛行的时代,再用电脑就不太合适了。 是时候应该反击了 当我看到@鄢得諼草 的那几篇黑我黑到体无完肤的#极客爱情# @Phodal 故事的时候,我发现我竟无言以对。或许,作为一名程序员,我们或多或少都有这样的共性。 ...

    XGBCCC 评论0 收藏0
  • Promise快速入门

    摘要:周五就想写这篇文章,但是无奈花花世界的诱惑太多就一直拖到了今天,自责遍进入正题对象用于表示一个异步操作的最终状态完成或失败,以及其返回的值。 周五就想写这篇文章,但是无奈花花世界的诱惑太多……就一直拖到了今天,自责1e4遍;进入正题Promise: Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。 上为MDNPromise的定义;ES6规定Promis...

    bergwhite 评论0 收藏0
  • ES6 系列之我们来聊聊 Async

    摘要:标准引入了函数,使得异步操作变得更加方便。在异步处理上,函数就是函数的语法糖。在实际项目中,错误处理逻辑可能会很复杂,这会导致冗余的代码。的出现使得就可以捕获同步和异步的错误。如果有错误或者不严谨的地方,请务必给予指正,十分感谢。 async ES2017 标准引入了 async 函数,使得异步操作变得更加方便。 在异步处理上,async 函数就是 Generator 函数的语法糖。 ...

    Songlcy 评论0 收藏0
  • 实现简易 ES6 Promise 功能 (二)

    摘要:今天我们接着上次的内容继续扯,如何实现数据传递以及当回调函数返回一个新的上篇已完成的代码测试代码上面的结果,就是我们要实现的。然后,等到下次需要的时候,再传给下一个回调函数。先来修改方法,因为回调函数都是在这里运行的。 上一篇文章【实现简易 ES6 Promise 功能 (一)】实现了基本的异步功能。今天我们接着上次的内容继续扯,如何实现【数据传递】以及当【回调函数返回一个新的prom...

    sPeng 评论0 收藏0

发表评论

0条评论

weizx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<