在本机Javascript中链接Promise

Ray*_*ser 3 javascript ecmascript-6 es6-promise

我想将3个承诺链接在一起但是有些行为我无法弄清楚它resolvereject功能.为了问这个问题,我简化了我的代码:

function testP(num) {
  return new Promise((resolve, reject) => {
    console.log('Do Work', num);
    reject(num);
  });
}

function testPromises() {
  return new Promise((resolve, reject) => {
      testP(1)
        .then(testP(2))
        .then(testP(3))
        .then(resolve)
        .catch(reject);
  });
};

const theTest = testPromises().then(()=>{
    console.log("all done");
}).catch(err => {
    console.log("ERR", err);
});
Run Code Online (Sandbox Code Playgroud)

我在输出中看到的是:

Do Work 1
Do Work 2
Do Work 3
ERR 1
Run Code Online (Sandbox Code Playgroud)

为什么代码会到达Do Work 2,Do Work 3如果第一个承诺reject立即命中?我的理解是then函数等待执行时resolvereject之前的承诺.

T.J*_*der 5

因为当你这样做

.then(testP(2))
Run Code Online (Sandbox Code Playgroud)

你立即无条件地调用 testP,传入2,然后将其返回值传递给.then,完全按照foo(bar()) 调用 方式bar并将其返回值传递给foo.

这段代码:

  testP(1)
    .then(testP(2))
    .then(testP(3))
    .then(resolve)
    .catch(reject);
Run Code Online (Sandbox Code Playgroud)

像这样评估(省略一些细节):

  • testP使用值1 调用并记住结果值为p1
  • testP使用值2 调用
  • p1.then使用该调用的结果调用并将结果值记为P2
  • testP使用值3 调用
  • p2.then使用该调用的结果调用并记住结果值为p3
  • p3.then使用值调用resolve并记住结果为p4
  • p4.catch用值调用reject
  • 调用reject第一次调用函数testP与值1
  • 使用值1 调用rejectfromtestPromises

如果你希望它testP等到第一个结算,你不要调用它,你传递一个引用:

.then(testP)
Run Code Online (Sandbox Code Playgroud)

如果您希望它有一个参数,请使用bind:

.then(testP.bind(null, 2))
Run Code Online (Sandbox Code Playgroud)

或内联函数:

.then(function() {
    return testP(2);
 })
Run Code Online (Sandbox Code Playgroud)

示例(需要浏览器Promise):

function testP(num) {
  return new Promise((resolve, reject) => {
    console.log('Do Work', num);
    reject(num);
  });
}

function testPromises() {
  return new Promise((resolve, reject) => {
      testP(1)
        .then(testP.bind(null, 2))
        .then(testP.bind(null, 3))
        .then(resolve)
        .catch(reject);
  });
};

const theTest = testPromises().then(()=>{
    console.log("all done");
}).catch(err => {
    console.log("ERR", err);
});
Run Code Online (Sandbox Code Playgroud)