完成一个承诺,在开始下一个承诺之前,在一个长名单中

时间:2017-09-18 13:54:50

标签: javascript node.js promise chaining

我最近发现了javascript承诺。广告的好处是通过链接然后条款来进行干净的嵌套。

我的代码按预期工作,但嵌套增长与使用回调时一样难看。有没有更好的方法来使用链接来删除所有这些嵌套?注意我需要在任务n + 1开始之前完成任务n。

非常简单的固定示例

'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" )})

真实代码接收一系列要按顺序处理的内容。 只有当步骤序列被指定为代码时,上面建议的格式才适用。似乎应该有某种Promise.do_these_sequentialy,而不是我的代码明确构建promise链。如下:

'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 个答案:

答案 0 :(得分:1)

你误解了Promises是如何运作的。您可以链接返回值以及Promise实例,并沿着链进一步传递它们:

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

没有必要嵌套它们。

答案 1 :(得分:1)

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

您可以使代码更加平坦。 另外explicit construction is an antipattern

答案 2 :(得分:1)

我个人喜欢这种格式的外观和使用方式

foo(){
  P1().then(()=>{
    return P2();
  }).then(()=>{
    return P3();
  }).catch((err)=>{
    //handle errors
  });
}

答案 3 :(得分:0)

看看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()