// importing required builtin modules
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydb');
// schema for email
var emailSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
html: String,
text: String,
headers: {},
subject: String,
references: [String],
messageId: String,
inReplyTo: [String],
priority: String,
from: [],
replyto: [String],
to: [],
date: Date,
receivedDate: Date,
attachments: [],
read: { type: Boolean, default: 0 },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
active: { type: Boolean, default: 1 },
labels: [String]
});
// schema for thread
var threadSchema = mongoose.Schema({
threadedEmails: [{ type: String, ref: 'Email' }],
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
});
// defining models
var Email = mongoose.model('Email', emailSchema);
var Thread = mongoose.model('Thread', threadSchema);
module.exports = Email;
module.exports = Thread;
// function to return an array which contains yet anohter array of emails each representing a thread
function doCalls() {
threads = [];
// a promise that always resolves
return new Promise(function (resolve, reject) {
resolve(1);
})
// this returns the threads as expected
.then(function (result) {
return Promise.resolve(
Thread.find({}, { threadedEmails: 1, _id: 0 }).then(
(_threads) => { return _threads }, //resolve
(err) => { reject(err); } //reject
)
)
})
// this does not returns the emails array as i expect
.then(function (threads) {
allEmails = [];
threads.forEach(thread => {
// Start off with a promise that always resolves
var sequence = Promise.resolve();
sequence = sequence.then(function (result) {
console.log('then of first foreach');
//query to make a database call to get all the emails whoes messageId's matchs
query = Email.find({ messageId: { "$in": thread.threadedEmails } });
query.exec((err, result) => {
if (err) throw err;
allEmails.push(result); //but this does not works because the code execution moves ahead
console.log(result); //this console log returns the value
});
})
})
//----------------- this is the problematic code here this array returns empty ----------------//
console.log(allEmails);
})
}
doCalls()
.then(function (allEmails) {
// console.log(allEmails);
});
我已经在代码中的任何地方写了评论,尽管让我解释一下我正在尝试的内容
希望我明确表示,如果我还需要提供其他任何内容,请成为我的向导并告诉我。
答案 0 :(得分:0)
forEach块在返回其中的任何异步操作之前完成。因此,当你调试它时,你的allEmails数组仍然是空的。
您需要做的是构建一个使用“结果”解析的Promise数组,然后将此数组提供给Promise.all(arrayOfPromises),这将解决您的所有承诺何时解决。
Promise.all非常友好,可以为您解决结果数组。 你的最后一个看起来像是:
.then(function (threads) {
const promiseArray = [];
threads.forEach(thread => promiseArray.push(
Promise.resolve(Email.find({ messageId: { "$in": thread.threadedEmails } }))
)
);
return Promise.all(promiseArray);
}
话虽如此,对于你想要实现的目标,Model.aggregate()将是一个更优雅的解决方案。
希望这有帮助