代码之家  ›  专栏  ›  技术社区  ›  grabbag

在开始下一个承诺之前,完成一个承诺

  •  1
  • grabbag  · 技术社区  · 7 年前

    我最近发现了javascript承诺。广告中的一个好处是通过链接then子句进行干净嵌套。

    非常简单的固定示例

    'use strict';
    
    function P1() {
    
        return new Promise((resolve) => {
            console.log("starting 1")
    
            setTimeout(() => {
                console.log("done 1")
                resolve();
            }, 100)
        })
    }
    
    function P2() {
    
        return new Promise((resolve) => {
            console.log("must start 2 only after 1 is done")
    
            setTimeout(() => {
                console.log("done 2")
                resolve();
            }, 50)
        })
    }
    
    function P3() {
    
        return new Promise((resolve) => {
            console.log("must start 3 only after 3 is done")
    
            setTimeout(() => {
                console.log("done 3")
                resolve();
            }, 10)
        })
    }
    
    console.log("this works, but if list was long, nesting would be terribly deep");
    // start 1, done 1, start 2, done 2, start 3, done 3.
    P1().then(() => {
        P2().then(() => {
            P3()
        })
    })
    

    根据我应该做的反馈

    P1().then(() => {
        return P2()
    }).then(() => {
        return P3()
    }).catch(() => { console.log("yikes something failed" )})
    

    真正的代码接收一系列要顺序处理的内容。

    'use strict';
    
    
    function driver(single_command) {
        console.log("executing " + single_command);
    
        // various amounts of time to complete command
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("completed " + single_command);
                resolve()
            }, Math.random()*1000)
        })
    }
    
    function execute_series_of_commands_sequentialy(commands) {
        var P = driver(commands.shift());
    
        if (commands.length > 0) {
            return P.then(() => { return execute_series_of_commands_sequentialy(commands) })
        } else {
            return P
        }
    }
    
    execute_series_of_commands_sequentialy([1, 2, 3, 4, 5, 6, 7, 8, 9]).then(() => {
        console.log("test all done")
    })
    
    4 回复  |  直到 7 年前
        1
  •  1
  •   kharandziuk    7 年前
    P1()
    .then(() => P2())
    .then(() => P3())
    

    explicit construction is an antipattern

        2
  •  1
  •   lukaleli    7 年前

    你误解了承诺的作用。您可以链接返回值和承诺实例,并沿链进一步传递它们:

    P1()
    .then(() => P2())
    .then(() => P3())
    

        3
  •  1
  •   Guy who types fast    7 年前

    就我个人而言,我喜欢这种格式的外观,这就是我使用的格式

    foo(){
      P1().then(()=>{
        return P2();
      }).then(()=>{
        return P3();
      }).catch((err)=>{
        //handle errors
      });
    }
    
        4
  •  0
  •   Jeremy Thille    7 年前

    看看async/await,它大大简化了承诺的编写。

    JavaScript’s Async/Await Blows Promises Away

    基本上,它包括编写异步函数,如同步代码:

    async function P(number) {
        return new Promise((resolve) => {
            console.log("starting "+number)
    
            setTimeout(() => {
                console.log("done "+number)
                resolve();
            }, 800)
        })
    }
    
    /* Or the ES6 version :
      const P = async (number) => new Promise((resolve) => { ... })
    */
    
    async function run(){
       await P(1)
       await P(2)
       await P(3)
       
       console.log("All done!")
    }
    
    run()