завершение одного обещания, прежде чем начинать следующее, в длинном списке

1

Недавно я обнаружил javascript-обещания. Рекламируемым преимуществом является чистое вложение путем цепочки, а затем предложения.

Мой код работает так, как ожидалось, но вложенность растет так же безобразно, как когда я использовал обратные вызовы. Есть ли лучший способ использовать цепочку для удаления всего этого гнездования? Примечание. Мне нужно выполнить задачу 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")
})
  • 0
    Это действительно вступает в игру с веб-крипто-API. Например, если вы хотите создать ключ, который можно использовать на странице, но вы не можете разрешить какое-либо шифрование / дешифрование до тех пор, пока ключ не будет создан, вы столкнетесь с ловушкой 22. Функция importKey является асинхронной, и трудно убедиться, что ключ создан, прежде чем разрешить шифрование или дешифрование.
Теги:
promise
chaining

4 ответа

1
Лучший ответ
P1()
.then(() => P2())
.then(() => P3())

Вы можете сделать свой код более плоским. Также явная конструкция является антипаттерн

1

Лично мне нравится, как выглядит этот формат и что я использую

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

Вы неправильно поняли, как работают Обещания. Вы можете связать возвращаемые значения, а также экземпляры Promise и передать их далее по цепочке:

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

Там нет необходимости их гнездовать.

0

Взгляните на async/wait, что значительно упрощает написание обещаний.

JavaScripts Async/Await Blows Promises Away

В принципе, он заключается в написании таких функций async, как код синхронизации:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню