V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
haozhang
V2EX  ›  Node.js

对于 Chaining Promises 的理解,不知道对不对,欢迎纠错。

  •  1
     
  •   haozhang · 2015-07-30 21:22:10 +08:00 · 3386 次点击
    这是一个创建于 3196 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我对于链式Promise的理解是这样,不知道对不对:

    首先.then和.catch都会返回一个新的promise对象,这个second promise对象的
    状态是根据第一个promise对象的回调函数执行的情况来决定的。如果第一个promise对象的回调函数(不管是fulfillment handler还是rejection handler都一样)正常执行,没有抛出错误,则second promise对象的状态变成fulfilled,并且使之变成的fulfilled状态的值就是前一个promise对象的回调函数中返回的值。

    let p1 = new Promise((resolve, reject) => {
        resolve(42);
    });
    
    p1
        .then(
            (value) => {
                console.log(value); // 42
            }
        )
        .then(
            (value) => {
                console.log(value); // undefined
            }
        );
    

    上面代码的执行结果如下:
    42
    undefined

    而如果在第一个promise对象的回调函数中抛出了错误,则.then方法返回的second promise对象的状态就变成了rejected,并且使之变成rejected状态的值就是上一个promise对象的回调函数中抛出的错误。

    var p1 = new Promise((resolve, reject) => {
        reject(new Error("p1 error"));
    });
    
    p1
        .then(
            (value) => { 
                console.log(value);     
            },
            (error) => { 
                console.log(error); // [Error: p1 error]
                throw new Error("2"); 
            }
        )
        .then(
            (value) => { 
                console.log(value); 
            },
            (error) => { 
                console.log(error); // [Error: 2]
            }
        );
    

    上面代码的执行结果如下:
    [Error: p1 error]
    [Error: 2]

    当然,在第一个promise对象的回调函数中还能够返回一个promise对象,记这个promsie对象为A,则.then方法返回的second promise对象的状态就跟随这个A来了:

    var p1 = new Promise((resolve, reject) => {
        resolve(1);
    });
    
    p1
        .then(
            (value) => {
                console.log(value); // 1
                return new Promise((resolve, reject) => {
                    reject(new Error("promsie A was rejected"));
                });
            }
        )
        .then(
            (value) => {
                // never called
            },
            (error) => {
                console.log(error); // [Error: promsie A was rejected]
            }
        );
    

    上面代码的执行结果如下:
    1
    [Error: promsie A was rejected]

    然后所有的链式调用都遵循上面的规则,不管链式有多长。再强调一下:对调函数包括fulfillment handler和rejection handler,都是遵守上面的规则的。

    Promise对象可以添加无数的回调函数,只要一改变状态,就开始执行添加给它的回调函数,并且执行回调函数的顺序就是添加的顺序:

    var p1 = new Promise((resolve, reject) => {
        resolve(1);
    });
    
    p1
        .then(
            (value) => {console.log("the first fulfillment handler", value)}
        );
    
    
    p1
        .then(
            (value) => {console.log("the second fulfillment handler", value)}
        );
    
    
    p1
        .then(
            (value) => {console.log("the third fulfillment handler", value)}
        );
    

    上面代码的执行结果如下:
    the first fulfillment handler 1
    the second fulfillment handler 1
    the third fulfillment handler 1

    要注意的是上面的写法和链式的写法(3个连续的.then)的意义是不一样的。

    我的理解就是这些,不知道对不对,欢迎纠错。

    12 条回复    2015-08-07 10:01:28 +08:00
    haozhang
        1
    haozhang  
    OP
       2015-07-30 21:23:21 +08:00
    haozhang
        2
    haozhang  
    OP
       2015-07-30 23:20:43 +08:00 via iPhone
    没人鸟我...
    czheo
        3
    czheo  
       2015-07-30 23:24:27 +08:00
    基本正确。补充一点
    1. then的callback既可以返回一个Promise,也可以返回一个value
    2. 如果返回Promise,这个Promise的状态会chain 给下一个then
    3. 如果返回value,这个value会传给下一个then的callback
    haozhang
        4
    haozhang  
    OP
       2015-07-30 23:27:54 +08:00 via iPhone
    @czheo 你补充的点我都有说啊。
    czheo
        5
    czheo  
       2015-07-30 23:30:38 +08:00   ❤️ 1
    因为你的callback都没有返回值,唯一一个返回的是一个Promise,所以。。。可能是我看漏了。
    我看你的理解基本没问题。
    haozhang
        6
    haozhang  
    OP
       2015-07-30 23:34:33 +08:00 via iPhone
    @czheo 函数不是默认返回undefined嘛,→_→
    lujiajing1126
        7
    lujiajing1126  
       2015-07-30 23:36:39 +08:00 via iPad
    promise-spec是标准。。所有实现都是按照标准来的。。

    说这么多还不如看看标准和实现
    haozhang
        8
    haozhang  
    OP
       2015-07-30 23:39:56 +08:00 via iPhone
    ysmood
        9
    ysmood  
       2015-07-31 06:25:22 +08:00
    @haozhang 读读这篇,或许会有帮助你理解 promise: https://github.com/ysmood/yaku/blob/master/docs/lazyTree.md

    然后打个硬广 https://github.com/ysmood/yaku
    这个库的异常处理机制在业界应该是最前沿的之一,对初学者会很友好。
    haozhang
        10
    haozhang  
    OP
       2015-07-31 07:26:56 +08:00 via iPhone
    @ysmood →_→ 嗯
    hanan321
        11
    hanan321  
       2015-07-31 10:55:38 +08:00
    以前写过一个promise练手 https://github.com/hanan198501/promise
    xieranmaya
        12
    xieranmaya  
       2015-08-07 10:01:28 +08:00
    https://promisesaplus.com/
    请看标准,讲的非常详细
    最近还实现了一个
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2572 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 154ms · UTC 12:42 · PVG 20:42 · LAX 05:42 · JFK 08:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.