Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案
Posted
技术标签:
【中文标题】Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案【英文标题】:Promise.all() returns undefined array of Promise <Pending>'s, despite similar solutions returning successful alternatives 【发布时间】:2019-10-03 14:48:13 【问题描述】:我正在构建一个网络应用程序,允许用户查看项目仪表板,这些项目又具有单独的部分(a、b 和 c),仪表板将显示为完整 (o) 或不完整 (x)如下图所示。这允许用户直接导航到缺少信息的页面,因为需要项目的所有信息才能进入下一阶段。
Item | a | b | c | Next Stage?
------------------------------
abc | x | o | x | No
def | x | x | x | No
ghi | o | o | o | Yes
在每个项目(例如 abc)中,它可以有许多子项目,这些子项目必须全部完成才能将该项目的 a、b 或 c 部分标记为完成。这是通过一系列嵌套的承诺来实现的,这些承诺在更新子项时更新“完整性”变量。但是,当尝试将变量从子项(a's、b's、c's)的范围传输到父项(abc、def、ghi)时,会出现问题。我以前使用嵌套的 Promise 没有实现 async/await 并且因为这是该项目范围内的 Promise 的最终用法,我犹豫采用不同的方式来解决这个问题(但我不反对它)。
当前实施:
exports.loadDashboard = (req, res, next) =>
Item.find()
.where("user").equals(req.session.user)
.select()
.exec()
.then(docs =>
const response =
items: docs.map(doc =>
const aPromise = Feature.find().where("projectID").equals(doc._id).select("aComplete").exec();
const bPromise = Feature.find().where("projectID").equals(doc._id).select("bComplete").exec();
const cPromise = Feature.find().where("projectID").equals(doc._id).select("cComplete").exec();
Promise.all([aPromise, bPromise, cPromise]).then(result =>
return
_id: doc._id,
user: doc.user,
aComplete: result[0],
bComplete: result[1],
cComplete: result[2]
// )
),
userSessionID: req.session.user
if(req.session.user != null)
console.log(response);
res.render("dashboard", response);
else
res.redirect("login");
)
.catch(err=>
console.log(err);
res.status(500).json(
error: err
);
);
...授予response
的:
items: [ undefined, undefined, undefined ],
userSessionID: '1'
这些未定义的项目是Promise <Pending>
类型,类似的问题已经以类似的方式解决了,但这次我很卡住。我的问题是,是否有可能在不深入研究 async/await 的情况下解决这个问题,或者我应该硬着头皮,如果是这样,我将非常感谢提供的任何帮助。
感谢阅读
【问题讨论】:
不要尝试在响应对象中构建所有内容。做你的Promise.all
,然后从它的then
回调,建立你的回应。否则,您甚至在完成之前就返回您的回复。
谢谢@Keith,虽然我不确定我是否理解 - 我已经在Promise.all
的then
回调中建立了我的回复,不是吗?我看不到如何在调用它们之前调用Promise
函数,因为我需要doc
范围来获取_id
s?
【参考方案1】:
这里发生了很多事情,如果可能的话,切换到使用 async/await 而不是使用 Promises,因为这是使您的代码难以维护的主要原因之一。我相信您可能只需要实际返回正确的值。
您的 .map 函数没有返回任何内容,这可能是您收到 [undefined, undefined, undefined] 的主要原因。
exports.loadDashboard = (req, res, next) =>
// don't use "where", if you don't have to
Item.find(user: req.session.user)
.exec()
.then(docs =>
const items = docs.map(doc =>
const aPromise = Feature.find().where("projectID").equals(doc._id).select("aComplete").exec();
const bPromise = Feature.find().where("projectID").equals(doc._id).select("bComplete").exec();
const cPromise = Feature.find().where("projectID").equals(doc._id).select("cComplete").exec();
// THIS IS WHERE I ADDED THE RETURN!
return Promise.all([aPromise, bPromise, cPromise])
.then(result =>
return
_id: doc._id,
user: doc.user,
aComplete: result[0],
bComplete: result[1],
cComplete: result[2]
))
return Promise.all(items);
)
.then(items =>
const response =
userSessionID: req.session.user,
items
;
// also check if .user is undefined, the null check is then optional
if(!req.session.user || req.session.user === null)
return res.redirect("login");
console.log(response);
return res.render("dashboard", response);
).catch(error =>
console.log(error);
res.status(500).json(error);
);
看看情况如何。我相信可能仍然存在一些问题,但该大纲应该会让您更容易使用它。
【讨论】:
绝对惊人,这完全符合我的预期。非常感谢 BenSower 和 @Keith 的投入和帮助! 没问题。正如我已经提到的,我建议您查看更新的 async/await 语法,这使得编写此代码更容易和更清晰。 我一定会的,这个项目是鲁莽地跳入 NoSQL 和异步代码的未知世界,但至少下次我会(稍微)准备好!以上是关于Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案的主要内容,如果未能解决你的问题,请参考以下文章
理解Promise.all,Promise.all与Promise.race的区别,如何让Promise.all在rejected后依然返回resolved状态