链接承诺不会将数据从一个 .then 传递到下一个

Posted

技术标签:

【中文标题】链接承诺不会将数据从一个 .then 传递到下一个【英文标题】:Chaining promises doesn't pass data from one .then to the next 【发布时间】:2020-01-06 20:12:21 【问题描述】:

我正在尝试在 mocha 测试中链接承诺,但似乎数据没有从一个 .then 传递到下一个。

我正在尝试测试一个可以更新数据库中一行的函数。然后我想查询该行以查看是否已应用更改。

我的测试:

    it("should update the status of an appointment", function(done) 
      new Promise((resolve, reject) => 
        updateStatus(testDb, 3, "In Progress", function(err) 
          if (err) reject(err);
          resolve();
        );
      )
        .then(() => 
          new Promise((resolve, reject) => 
            getOneAppointment(testDb, 3, function(err, appt) 
              if (err) reject(err);
              resolve(appt);
            );
          );
        )
        .then(appt => 
          console.log(appt);
          expect(appt).deep.equal(updatedResponse);
          done();
        )
        .catch(err => 
          done(err);
        );
    );

第二个.then 中的console.log 打印为未定义。

【问题讨论】:

回报你的新承诺 知道没有任何return 语句的函数有一个隐含 return undefined 很有用...知道箭头函数的简短版本也很有用例如...arg => blah() 等同于arg => return blah();...所以至少上面的一个地方可以删除一些 而不是添加return @Trevor 可以,但你能解释一下为什么我不需要返回第一个承诺吗? 理论上你应该把它归还给某物。使用 new 关键字而不将值存储到某些东西并不是很好。但是您的第一个承诺不会解析为一个值,因此返回它会给出未定义的结果,就像不返回它一样。作为一种习惯,对于任何没有真正返回值的承诺,我通常返回 true 表示成功,而返回 false 表示失败。 【参考方案1】:

如 cmets 中所述,您应该返回新的 Promise。下面是一个演示 Promise 链接的模拟示例:

new Promise( function (resolve, reject) 
    console.log("Should update the status of an appopintment");
    resolve(  status: 1  );
 )
.then( function ( statusResult ) 
    return new Promise( function (resolve, reject) 
        console.log("updateStatus");
        resolve(  update: 2  );
     );
 )
.then( function ( updateResult) 
    return new Promise( function (resolve, reject) 
        console.log("getOneAppointment");
        resolve(  appointment: 3  );
     );
 )
.then( function( appointmentResult ) 
    return new Promise( function (resolve, reject) 
        console.log("updatedResponse");
        resolve(  update: 4  );
     );
 )
.then( function( updateResult ) 
    console.log("Done");
 )

【讨论】:

【参考方案2】:

它不起作用,因为代码没有为第二个 then 指定 return。我们需要指定return,因为我们想在之后使用then

it("should update the status of an appointment", function(done) 
  new Promise((resolve, reject) => 
    updateStatus(testDb, 3, "In Progress", function(err) 
      if (err) reject(err);
      resolve();
    );
  )
    .then(() => 
      // specify `return` here
      return new Promise((resolve, reject) => 
        getOneAppointment(testDb, 3, function(err, appt) 
          if (err) reject(err);
          resolve(appt);
        );
      );
    )
    .then(appt =>  // so we can proceed with this
      console.log(appt);
      expect(appt).deep.equal(updatedResponse);
      done();
    )
    .catch(err => 
      done(err);
    );
);

您无需在第一个承诺中指定return,因为您在此处使用done(回调)。如果你添加return,它会显示错误

Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

Mocha 确实可以支持 Promise(无需指定 done 作为回调)。这是没有done 的替代方案,我认为它更干净:

it("should update the status of an appointment", function()  // remove done
  // add return
  return new Promise((resolve, reject) => 
    updateStatus(testDb, 3, "In Progress", function(err) 
      if (err) reject(err);
      resolve();
    );
  )
    .then(() => 
      // specify `return` here
      return new Promise((resolve, reject) => 
        getOneAppointment(testDb, 3, function(err, appt) 
          if (err) reject(err);
          resolve(appt);
        );
      );
    )
    .then(appt =>  // so we can proceed with this
      console.log(appt);
      expect(appt).deep.equal(updatedResponse);
      // remove done()
    );
);

参考资料:

https://mochajs.org/#working-with-promises

希望对你有帮助

【讨论】:

以上是关于链接承诺不会将数据从一个 .then 传递到下一个的主要内容,如果未能解决你的问题,请参考以下文章

承诺,如何将变量传递给 .then 函数

将承诺的结果链接并传递给进一步的承诺[重复]

如何在 JS 中使用 try、catch、.then 链接和异步等待来解决承诺?

将已解决的承诺值传递到最终的“then”链的最佳方法是啥[重复]

isKindOfClass 在 PromiseKit 中返回 nil 吗?

猫鼬承诺永远不会到达 .then()