JavaScript链接的Promises意外的解析顺序

时间:2018-09-05 16:55:21

标签: javascript concurrency promise es6-promise

我对这两个不同的函数的执行感到困惑,我期望它们以相同的顺序进行解析,但是显然,它们不是。

    // 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 :(得分:3)

您实际上并不是在这里链接诺言,您只是将多个函数附加到Promise上,这些函数可以同时执行。

要实现承诺,请依次写下.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!' ) );

答案 1 :(得分:2)

承诺的关键方面之一是thencatch 返回新的承诺。他们返回的承诺将根据其回调函数的作用而解决或拒绝:

  • 如果它返回一个简单值,则承诺将使用该值进行解析
  • 如果它抛出一个值(throw),则诺言将拒绝该值
  • 如果它返回一个 promise ,则该诺言将成为该其他诺言的奴隶,并且直到/除非回调返回的诺言能够实现,否则该诺言不会被解决/拒绝

这就是为什么 chaining 可以满足您的期望,但是第二个示例(不使用更改)却没有。第二个示例中的所有四个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);
});

答案 2 :(得分:0)

第一个示例的关键方面是.then(promiseDelay)返回的 promise 会延迟执行一秒钟,因此下一个promise会在解决后执行,因为每个{ {1}}接收location /example { port_in_redirect off; proxy_pass https://example.apps.svc.cluster.local:8443; } 之前的结果作为参数,从而创建一个链。

在第二个示例中,每一行都返回一个新承诺,但是由于没有等待,因此每一行都将按顺序进行求值,并且承诺只是延迟执行,因此带有{{ 1}}将比延迟一秒的执行先完成执行。