JavaScript в цепочке обещает неожиданный порядок разрешения - PullRequest
0 голосов
/ 05 сентября 2018

Я запутался в выполнении этих двух различных функций, я ожидал, что они разрешатся в одном и том же порядке, но, по-видимому, они этого не делают.

    // given this function:
let promiseDelay = () => new Promise( resolve => { setTimeout( () => { console.log( '========' ); resolve(); }, 1000 ) } );

// execution 1:
const promise1 = Promise.resolve( {} ).then( promiseDelay ).then( () => console.log( 'Job done!' ) ).then( promiseDelay ).then( () => console.log( 'Job done!' ) );

// given this function:
const promiseDelay = () => new Promise( resolve => { setTimeout( () => { console.log( '========' ); resolve(); }, 1000 ) } );

// execution 2:
const promise = Promise.resolve( {} );
promise.then( promiseDelay );
promise.then( () => console.log( 'Job done!' ) );
promise.then( promiseDelay );
promise.then( () => console.log( 'Job done!' ) );

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Одним из ключевых аспектов обещаний является то, что then и catch возвращают новые обещания . Обещание, которое они возвращают, разрешается или отклоняется в зависимости от того, что делает их функция обратного вызова:

  • Если возвращается простое значение, обещание разрешается с этим значением
  • Если выбрасывается значение (throw), обещание отклоняется с этим значением
  • Если он возвращает обещание , обещание подчиняется этому другому обещанию и не разрешается / не отклоняется до тех пор, пока обещание, возвращенное обратным вызовом, не выполнит

Вот почему цепочка делает то, что вы ожидаете, а ваш второй пример (который не использует чаннинг) - нет. Все четыре из этих then обработчиков во втором примере независимы друг от друга, тогда как в первом примере они ждут друг друга.

Вот пример, иллюстрирующий, как then возвращает новое обещание, см. Встроенные комментарии:

const delay = (ms, value) =>
    new Promise(resolve => setTimeout(resolve, ms, value));

const p1 = delay(100, "p1 result");

const p2 = p1.then(result => {
    console.log("p2 handler got: " + result);
    return delay(500, "p2 result");
});
// This shows false: `then` returns a new promise
console.log(p1 === p2);

const p3 = p1.then(result => {
    console.log("p3 handler got: " + result);
    return "p3 result"; // no delay
});
// Also shows false: `then` returns a new promise *each time*
console.log(p2 === p3);

// Notice that p4's handler doesn't get called
// until the promise returned in p3's handler resolves...
const p4 = p2.then(result => {
    console.log("p4 handler got: " + result);
});
// ...but p5's gets called earlier, because p3's
// handler returns a simple value, which just
// gets wrapped in a resolved promise
const p5 = p3.then(result => {
    console.log("p5 handler got: " + result);
});
0 голосов
/ 05 сентября 2018

Ключевым аспектом первого примера является то, что .then (promiseDelay) возвращает обещание , которое задерживает выполнение на одну секунду, поэтому следующее обещание выполняется только после того, как это разрешено, так как каждый .then получает в качестве параметра результат .then before, создавая цепочку.

Во втором примере каждая строка возвращает новое обещание , но так как ожидания не ожидаются, каждая строка оценивается последовательно, и обещания просто становятся отложенными выполнениями, поэтому те с console.log завершит выполнение первым, чем те, с задержкой в ​​одну секунду.

0 голосов
/ 05 сентября 2018

Вы на самом деле здесь не связываете обещания, вы просто присоединяете к обещанию несколько функций, которые выполняются одновременно.

Чтобы связать обещания, напишите следующие .then() с друг за другом:

// given this function:
promiseDelay = () => new Promise( resolve => { setTimeout( () => { console.log( '========' ); resolve(); }, 1000 ) } );

// execution 1:
promise = Promise.resolve( {} ).then( promiseDelay ).then( () => console.log( 'Job done!' ) ).then( promiseDelay ).then( () => console.log( 'Job done!' ) );

// execution 2:
promise = Promise.resolve( {} );
promise.then( promiseDelay )
    .then( () => console.log( 'Job done!' ) )
    .then( promiseDelay )
    .then( () => console.log( 'Job done!' ) );
...