前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >promise的使用方法

promise的使用方法

作者头像
OECOM
发布2020-07-02 11:27:29
5940
发布2020-07-02 11:27:29
举报
文章被收录于专栏:OECOMOECOM

异步操作作为JavaScript中的一大特色,解决了JavaScript单线程运行的一个难题,但是很多时候有问题也在于这上面。最大的问题之一,就是异步操作过多的时候,代码内会充斥着众多回调函数,乃至形成回调金字塔。为了解决回调函数带来的问题,Promise作为一种更优雅的异步解决方案被提出,最初只是一种实现接口规范,而到了es6,则是在语言层面就原生支持了Promise对象。

  1. Promise语法 promise的核心编程思想就是如果数据就绪(promised),那么(then)做点什么。 来看一下下面这个promise的使用示例 const promise = new Promise(function(resolve, reject) { // ... some code let randNumber = Math.random(); if (randNumber <0.5){ resolve(randNumber ); } else { reject('出错了'); } }); promise.then(data=>{ console.log(data); }).catch(error=>{ console.log(error); }) Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。 resolve函数的作用:将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去; reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为rejected), 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。 Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。其中如果执行了resolve则进入then方法,如果执行reject则进入catch方法,相当于是出了异常。 当然也不一定要写catch方法,在then里面可以接收两个参数,第二个参数就处理reject返回的信息。 promise.then(function(value) { // success }, function(error) { // failure }); 下面是一个使用then的例子。then方法返回的是一个新的Promise实例。 因此可以采用链式写法,即then方法后面再调用另一个then方法。 getJSON("/sendMs").then(function(json) { return json.post; }).then(function(post) { // ... }); 上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。 上面代码中,getJSON方法返回一个 Promise 对象;如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。 一般总是建议,Promise 对象后面要跟catch方法,这样可以处理 Promise 内部发生的错误。catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。 从上面的代码中我们还可以看出一个点,就是如果reject和resolve方法带有参数,则会将参数传递后相应的回调函数中。当然,这些值可以是任意类型的,有一种特殊的类型就是参数是一个promise对象。 const p1 = new Promise(function (resolve, reject) { // ... }); const p2 = new Promise(function (resolve, reject) { // ... resolve(p1); }) 在上面代码中,p1和p2都是promise实例对象,而p2的resolve函数将p1作为参数传入,即一个异步操作的结果返回的是另一个异步操作。 这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。 在使用promise的过程中需要注意的有以下几点:
    1. 调用resolve或reject并不会终结 Promise 的参数函数的执行。调用完成以后,后面的代码依然会执行,只不过再抛出错误,不会被捕获,等于没有抛出,后面的代码执行对于传入的参数没有任何影响。因为 Promise的状态一旦改变,就永久保持该状态,不会再变了。
    2. 如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。
  2. Promise.resolve()

有时需要将现有对象转为 Promise 对象,以便于链式的使用then方法,Promise.resolve方法就起到这个作用。

Promise.resolve等价于下面的写法。

代码语言:javascript
复制
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

Promise.resolve方法的参数分成四种情况。

1)参数是一个 Promise 实例

如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

2)参数是一个thenable对象

thenable对象指的是具有then方法的对象,比如下面这个对象。

代码语言:javascript
复制
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

代码语言:javascript
复制
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

上面代码中,thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42。

3)参数不是具有then方法的对象,或根本就不是对象。

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。

代码语言:javascript
复制
const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

上面代码生成一个新的 Promise 对象的实例p。由于字符串Hello不属于异步操作(判断方法是字符串对象不具有 then 方法),返回 Promise 实例的状态从一生成就是resolved,所以回调函数会立即执行。Promise.resolve方法的参数,会同时传给回调函数。

4)不带有任何参数

Promise.resolve方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。

所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve方法。

代码语言:javascript
复制
const p = Promise.resolve();

p.then(function () {
  // ...
});

上面代码的变量p就是一个 Promise 对象。需要注意的是,立即resolve的 Promise 对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。

代码语言:javascript
复制
setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');

// one
// two
// three

上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise. resolve()在本轮“事件循环”结束时执行,console.log('one')则是立即执行,因此最先输出。

文章参考链接:https://juejin.im/post/5af29a62f265da0b8f628973

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档