• 关于Promise:你可能不知道的6件事


    FROM ME :

    文章介绍了6个Promise的知识点:

      1、then() 返回一个 forked Promise(分叉的 Promise):返回的有两种情况;
      2、回调函数应该传递结果:在 promise 的上下文中,回调函数像普通的回调函数一样传递结果,返回的结果传给下一个回调函数;
      3、只能捕获来自上一级的异常
      4、错误能被恢复:在一个错误回调中,如果没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved。
      5、Promise 能被暂停:为了暂停当前的 promise,或者要它等待另一个 promise 完成,只需要简单地在 then() 函数中返回另一个 promise。
      6、resolved 状态的 Promise 不会立即执行

    原文:Six Things You Might Not Know About Promises

    译文:关于Promise:你可能不知道的6件事

    Promise 是一个非常简单的概念,即使你没有机会使用 Promise,你也可能阅读过一些关于 Promise 的文章。
    Promise 的价值在于使得异步代码以一个更可读的风格结构化,而不是因异步函数嵌套显得混乱不堪。这篇文章会接触到 6 个你可能不知道的关于 Promise 的事。

    开始列举之前,先看看怎么创建 Promise:

    var p = new Promise(function(resolve, reject) {
      resolve("hello world");
    });
    
    p.then(function(str) {
      alert(str);
    });

    1、then() 返回一个 forked Promise(分叉的 Promise)

    下面两段代码有什么不同?

    // Exhibit A
    var p = new Promise(/*...*/);
    p.then(func1);
    p.then(func2);
    
    // Exhibit B
    var p = new Promise(/*...*/);
    p.then(func1)
    .then(func2);

    如果你认为两段代码等价,那么你可能认为 promise 仅仅就是一维回调函数的数组。然而,这两段代码并不等价。p 每次调用 then() 都会返回一个 forked promise。因此,在A中,如果 func1 抛出一个异常,func2 依然能执行,而在B中,func2 不会被执行,因为第一次调用返回了一个新的 promise,由于func1 中抛出异常,这个 promise 被 rejected了,结果 func2 被跳过不执行了。

    2、回调函数应该传递结果

    下面的代码会 alert 什么?

    var p = new Promise(function(resolve, reject) {
      resolve("hello world");
    });
    
    p.then(function(str) {})
    .then(function(str) {
      alert(str);
    });

    第二个 then() 中的alert不是显示任何东西,因为在 promise 的上下文中,回调函数像普通的回调函数一样传递结果。promise 期望你的回调函数或者返回同一个结果,或者返回其它结果,返回的结果会被传给下一个回调。

    这和适配器传递结果的思想一样,看下面的示例:

    var feetToMetres = function(ft) { return ft*12*0.0254 };
    
    var p = new Promise(/*...*/);
    
    p.then(feetToMetres)
    .then(function(metres) {
      alert(metres);
    });

    3、只能捕获来自上一级的异常

    下面的两段代码有什么不同:

    // Exhibit A
    new Promise(function(resolve, reject) {
      resolve("hello world");
    })
    .then(
      function(str) {
        throw new Error("uh oh");
      },
      undefined
    )
    .then(
      undefined,
      function(error) {
        alert(error);
      }
    );
    // Exhibit B
    new Promise(function(resolve, reject) {
      resolve("hello world");
    })
    .then(
      function(str) {
        throw new Error("uh oh");
      },
      function(error) {
        alert(error);
      }
    );

    在A中,当第一个 then 抛出异常时,第二个 then 能捕获到该异常,并会弹出 'uh oh'。这符合只捕获来自上一级异常的规则。

    在B中,正确的回调函数和错误的回调函数在同一级,也就是说,尽管在回调中抛出了异常,但是这个异常不会被捕获。事实上,B中的错误回调只有在 promise 被 rejected 或者 promise 自身抛出一个异常时才会被执行。

    4、错误能被恢复

    在一个错误回调中,如果没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved。在下面的例子中,会弹出’I am saved’ 是因为第一个 then() 中的错误回调函数并没有重新抛出异常。

    var p = new Promise(function(resolve,reject){
        reject(new Error('pebkac'));
    });  
    
    p.then(
        undefined,
        function(error){ }
    )
     .then(
        function(str){
            alert('I am saved!');
        },
        function(error){
         alert('Bad computer!');
        }
    );   

    Promise 可被视为洋葱的皮层,每一次调用 then 都会被添加一层皮层,每一个皮层表示一个能被处理的状态,在皮层被处理之后,promise 会认为已经修复了错误,并准备进入下一个皮层。

    5、Promise 能被暂停

    仅仅因为你已经在一个 then() 函数中执行过代码,并不意味着你不能够暂停 promise 去做其他事情。为了暂停当前的 promise,或者要它等待另一个 promise 完成,只需要简单地在 then() 函数中返回另一个 promise。

    var = new Promise(/*...*/);   
    
    p.then(function(str){
        if(!loggedIn){
            return new Promise(/*...*/);
        }
    }) 
     .then(function(str){
        alert("Done!");
     });

    在上面的代码中,直到新的 promise 的状态是 resolved解析后,alert 才会显示。如果要在已经存在的异步代码中引入更多的依赖,这是一个很便利的方式。例如,你发现用户会话已经超时了,因此,你可能想要在继续执行后面的代码之前发起第二次登录。

    6、resolved 状态的 Promise 不会立即执行

    运行下面的代码会弹出什么呢?

    function runme() {
      var i = 0;
    
      new Promise(function(resolve) {
        resolve();
      })
      .then(function() {
        i += 2;
      });
      alert(i);
    }

    你可能会认为弹出2,因为 promise 已经是 resolved ,then() 会立即执行(同步)。然而,promise 规范要求所有回调都是异步的,因此,alert 执行时 i 的值还没有被修改。

    荐读

    Promise 的正确打开方式
    Promise/A+
    Promise 教程
    JavaScript Promises 102 - The 4 Promise Methods

  • 相关阅读:
    删除List集合中的元素你碰到过这样的陷阱吗?
    从spring框架中的事件驱动模型出发,优化实际应用开发代码
    SpringBoot启动原理及相关流程
    基于SpringBoot实现定时任务的设置(常用:定时清理数据库)
    C#开发中常用的加密解密方法
    http://go.microsoft.com/fwlink/?linkid问题
    移动端开发必须知道的小技巧
    工作中遇到的细节问题总结(二)
    redis分布式锁和消息队列
    join和wait
  • 原文地址:https://www.cnblogs.com/Chen-XiaoJun/p/6213832.html
Copyright © 2020-2023  润新知