猫鼬承诺永远不会到达 .then()
Posted
技术标签:
【中文标题】猫鼬承诺永远不会到达 .then()【英文标题】:Mongoose promise never gets to .then() 【发布时间】:2021-03-04 15:36:23 【问题描述】:我正在使用 q 并且我有多个 mongoose .exec()
承诺永远不会到达代码的 .then()
部分,所以永远不要让 q 解决。无法弄清楚为什么它永远不会回来。
var defer = q.defer();
var promises = [];
console.log('Exams:', exams.length);
for (var e=0; e<exams.length; e++)
console.log('Exams:', exams[e]._id);
var newPromise = Pupilexam.find( _exam: exams[e]._id ).populate('_user').exec()
.then((pupils) =>
console.log("Adding pupils", exams[e]._id);
exams[e].pupils = pupils;
resolve(exams[e]);
)
.catch((err) =>
reject(err);
);
console.log(typeof newPromise);
promises.push(newPromise);
console.log("Promised pushed");
q.all(promises).then(function(data)
console.log("q'd all");
defer.resolve(res.status(200).json(exams));
);
return defer;
Pupilexam.find().exec()
永远不会到达 .then()
,因此承诺永远不会解决,而延迟永远不会解决。为什么猫鼬会找不到.then()?我错过了什么?
*** 更新 ***
即使使用内置的 Promise,我们也会遇到同样的问题。 Pupilexams.find()
电话永远不会回来。
var promises = [];
for (var e=0; e<exams.length; e++)
console.log('e:', e);
console.log('Exam', exams[e]._id);
var newPromise = Pupilexam.find( _exam: exams[e]._id ).populate('_user').exec()
.then((pupils) =>
console.log("Adding pupils", exams[e]._id);
exams[e].pupils = pupils;
)
.catch(handleError(res));
promises.push(newPromise);
Promise.all(promises).then((exams) =>
console.log(values);
res.status(200).json(exams)
);
使用这种方法,我在调用 UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
时也会收到标题错误
** 需要额外的代码 **
function handleError(res, statusCode)
statusCode = statusCode || 500;
return function(err)
console.log(err.message);
res.status(statusCode).send(err);
;
【问题讨论】:
请问使用q
-promises 有什么特别的原因吗? Promise.all
通过本机承诺开箱即用地支持。
避免使用deferred antipattern (q.defer()
) 和Promise
constructor antipattern (resolve(exams[e]);
, reject(err);
)!
你的逻辑不对。如果了解您有一系列考试。您希望每次考试都将学生的数据添加到考试对象中。每个考试数组都是一个对象数组,您可以添加到每个对象属性,包括学生的信息。如果您需要处理来自 mongo 的错误,请再次调用它。在与学生信息进行考试之后。没有你的逻辑。另外如果你只是从mongo读取数据,推荐使用lean函数,
@eol 习惯。我在别处用过。但是当我使用 promises.all 时,我遇到了同样的问题。循环中的猫鼬调用永远不会返回并运行.then()
代码。
@Bergi 我已经更新了 promises.all 以避免,但遇到同样的问题。
【参考方案1】:
从你的代码看。
//(async) function
for (var e of exams)
try
const pupils = await Pupilexam.find( _exam: exams[e]._id
).populate('_user').exec().lean()
e.pupils = pupils
catch((err)
//handleError
;
res.status(200).json(data: exams)
也许这会告诉你你错了多少匹配
【讨论】:
我不相信这会奏效。 api 将在所有 mongoose 调用返回并填充考试之前返回,所以我不会得到我想要的数据。 你知道然后网站加入 => join.me/remote-work。我想证明自己。什么时候可以?【参考方案2】:看起来答案是,在这两行中,exams[e] 不在范围内,因为当承诺返回时,循环已经继续,所以 e 是错误的并且变得太高,所以它是错误的。
console.log("Adding pupils", exams[e]._id);
exams[e].pupils = pupils;
当我阅读@eol关于捕获的消息并决定正确捕获并输出时才发现。
【讨论】:
这无关紧要,不过我答对了。 问题是循环在promise返回之前改变了e的值,所以和数组中的相关考试不同步,导致了问题。【参考方案3】:我猜你确实在返回你的承诺,但你返回的是一个空的 json。 您的方法有两个问题:
你没有从你那里回来:应该返回学生并且它正在返回未定义
您正在记录我不知道它是什么的值
.then((pupils) =>
console.log("Adding pupils", exams[e]._id);
exams[e].pupils = pupils;
// you should return something // return pupils
)
promises.push(newPromise);
Promise.all(promises).then((exams) =>
// ['undefined', 'undefined', ...]
console.log(values);
res.status(200).json(exams)
);
【讨论】:
我故意不返回任何内容,因为我希望在测试时返回空值,但是是的,我需要一个返回值以供promise.all
发回。您在寻找哪些价值观? exams
是一个来自 mongo 的对象数组。【参考方案4】:
回答有关Cannot set headers after they are sent to the client
错误的更新问题。看起来您在 handleError
函数中向客户端发送了响应。现在,如果不止一次 Pupilexam.find
调用失败,handleError
将被调用两次,导致上述错误。
您应该将catch
-handler 移至Promise.all
调用:
const promises = [];
for (const exam of exams)
const newPromise = Pupilexam
.find( _exam: exam._id ).populate('_user').exec()
.then((pupils) =>
exam.pupils = pupils;
);
promises.push(newPromise);
Promise.all(promises)
.then((exams) =>
res.status(200).json(exams);
)
.catch(handleError(res));
【讨论】:
以上是关于猫鼬承诺永远不会到达 .then()的主要内容,如果未能解决你的问题,请参考以下文章