Promise使用须知

发布时间:2019-08-19 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Promise使用须知脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

一.关于Promise

promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。PRomise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

它代表一个异步操作。有三种状态:

  • PEnding(进行中): 初始状态, 初始状态,未完成或拒绝。
  • resolved(已完成): 意味着操作成功完成。又名fulfilled
  • rejected(已失败): 意味着操作失败。

有了Promise,就可以将异步操作以同步操作的流程表达出,但它也有如下缺点

  • 一旦创建它就会立即执行,无法中途取消。
  • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  • 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

二.应用示例

@H_512_53@1. 创建Promise@H_777_54@
VAR promise = new Promise(
    /* executor */ 
    function(resolve, reject){
        ...
    }
);

​ executor函数由Promise实现立即执行,传递resolve和reject函数. (在Promise构造函数之前调用执行器甚至返回创建的对象)

​ 在 executor 内部,promise有如下的状态变化可能:

​ 1. resolve被调用,promise由pending变为resolved,代表该Promise被成功解析(resolve)

​ 2.reject 被调用,promise由pending变为rejected,代表该Promise的值不能用于后续处理,即被拒绝了

注意:

  1. 如果在executor 方法的执行过程中抛出了任何异常,那么promise立即被拒绝(即相当于reject方法被调用),executor 的返回值也就会被忽略。
  2. 如果一个promise对象处在resolvedrejected状态而不是pending状态,那么它也可以被称为seTTLed状态。

2.处理Promise实例

  • then:Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。

    promise.then(function(value) {
      // success 状态为Resolved时调
    }, function(error) {  
      // failure 状态为Reject时调用
    });

then方法可以接受两个回调函数作为参数。

第一个回调函数:在promise的状态变成resolved时被调用。它的参数promise的resolve方法的返回值。

第二个回调函数:在promise的状态变成rejected时被调用。它的参数promise的reject方法的返回值。且为可选参数。

  • catchPromise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数

    promise.then(function(posts) {
      // ...
    }).catch(function(error) {
      console.LOG('发生错误!', error); // 处理 promise 和 前一个回调函数运行时发生的错误
    });
  • 扩展:

    • Promise.prototype.then和 Promise.prototype.catch方法返回 promises对象, 所以它们可以被链式调用。但此时返回的是以函数返回值生成的新的Promise实例,不是原来那个Promise实例

    Promise使用须知

注意问题:

  1. Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

3.将多个Promise实例,包装成一个新的Promise实例

  • Promise.all(ITerable) :当所有在可迭代参数中的 promises 已完成,或者第一个传递的 promise(指 reject)失败时,返回 promise。

    var p = Promise.all([p1, p2, P3]);
    • 当p1、p2和p3的状态均为resolved时p的状态为resolved
    • 当p1、p2或p3中的任意一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

具体的使用示例如下:

  • 情形一:全部成功的情况

    Promise.all([Promise.resolve('foo'),Promise.resolve('bar'),Promise.resolve('test')])
      .then(function(result){
                console.log(result); //结果为:[foo,bar,test]。即所有返回值的数组。
             })
       .catch(function(error) {
               console.log('error');    //不会被执行
       });
  • 情形二:全部失败或部分失败

    Promise.all([Promise.resolve('foo'),Promise.reject('barError'),Promise.reject('testError')])
       .then(function(result){
                console.log(result);            //成功回调  不会被执行
             })
       .catch(function(error) {
               console.log(error);    //结果为barError或testError。即第一个被reject的值。
       });
@H_750_406@三.常见的使用误区
  • 忘记添加 .catch()

通常情况,promise有如下两种处理方式:

// ------------    不好的写法   -------------
promise.then(function(data) {
    // success
  }, function(err) {   //仅处理promise运行时发生的错误。无法处理回调中的错误
    // error
  });

// ------------    好的写法    ------------
promise.then(function(data) {
    // success
}).catch(function(err) {   // 处理 promise 和 前一个回调函数运行时发生的错误
    // error 
});

因为promise抛出的错误不会传递到外层代码。当使用没有catch的第一种种写法时,成功回调的错误将无法被处理。因此比较好的方式是,总是使用catch方法。

  • 在then或者catch函数中不使用return

下面是在是用Promise时,一个很常见的错误写法:

//------------    不好的写法    ------------------
promise.then(function ({
  getUserInfo(userId);
}).then(function ({
  // 在这里可能希望在这个回调中使用用户信息,但你可能会发现它根本不存在
});

会发生上面的错误,是因为对Promise的返回及链式调用的理解不够。

每一个promise都会给你一个then()方法(或者catch,它们只是then(null,…)的语法糖)。这里我们是在then()方法的内部来看:

promise.then(function ({
  return getUserInfo(userId);
}).then(function (userInfo{
   HadleUser(userInfo);
}).catch(function(error) {
   console.log(error);
});

在回调中在有三种事可以做:

    1. 返回另一个promise

    如果getUserInfo返回一个Promise,则HadleUser将在该promise变为resolved后执行,并以该promise的返回作为入参。

    1. 返回一个同步值(或者undefined

    getUserInfo返回一个同步值,则改值会被包装成一个resolved状态的promise,HadleUser将被立刻执行,并以getUserInfo返回作为入参。

    1. 抛出一个同步错误

    getUserInfo返回一个同步错误,则该错误会被包装成一个rejected状态的promise,最终在catch中被捕获。此时HadleUser将不会被执行。

    • promises丢失

    你认为下面的代码会打印出什么?

    Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result{
      console.log(result);
    });

    如果你认为打印出bar,那你就大错特错了。它实际上会打印出foo。

    原因当你给then()传递一个非函数(比如一个promise)值的时候,它实际上会解释为then(null),这会导致之前的promise的结果丢失。

    四.最佳实践总结

    1. then方法中 永远 return 或 throw
    2. 如果 promise 链中可能出现错误,一定添加 catch
    3. 永远传递函数给 then 方法
    4. 不要把 promise 写成嵌套

    参考链接:

    Promise -JavaScript | MDN

    Promises 很酷,但很多人并没有理解就在用了

    Promise 对象

    脚本宝典总结

    以上是脚本宝典为你收集整理的Promise使用须知全部内容,希望文章能够帮你解决Promise使用须知所遇到的问题。

    如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。