链接承诺不会将数据从一个 .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 传递到下一个的主要内容,如果未能解决你的问题,请参考以下文章
如何在 JS 中使用 try、catch、.then 链接和异步等待来解决承诺?
将已解决的承诺值传递到最终的“then”链的最佳方法是啥[重复]