【问题标题】:completion of one promise, before starting the next, in a long list在开始下一个承诺之前完成一个承诺,在一个长长的列表中
【发布时间】:2017-09-18 13:54:49
【问题描述】:

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

我的代码按预期工作,但嵌套变得和我使用回调时一样难看。有没有更好的方法来使用 then 的链接来删除所有这些嵌套?请注意,我需要先完成任务 n,然后才能开始任务 n+1 中的任何内容。

非常简单的固定示例

'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,而不是我的代码明确地构建承诺链。如下:

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

【问题讨论】:

  • 这确实与网络加密 API 一起发挥作用。例如,如果您想创建一个可在页面上使用的密钥,但在创建密钥之前不允许进行任何加密/解密,您会遇到问题 22。importKey 函数是异步的,并且在允许进行加密或解密之前很难确保已创建密钥。

标签: javascript node.js promise chaining


【解决方案1】:
P1()
.then(() => P2())
.then(() => P3())

您可以使您的代码更加扁平化。 还有explicit construction is an antipattern

【讨论】:

    【解决方案2】:

    您误解了 Promise 的工作原理。您可以链接返回值以及 Promise 实例,并沿链进一步传递它们:

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

    没有必要嵌套它们。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        看看 async/await 大大简化了 Promise 的编写。

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

        【讨论】:

          猜你喜欢
          • 2017-05-02
          • 2016-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-18
          相关资源
          最近更新 更多