【问题标题】:fetch values from a loop inside .then in nodejs out in allemails array从 .then 中的循环中获取值,然后在 allemails 数组中的 nodejs 中
【发布时间】:2018-08-30 12:57:20
【问题描述】:
// 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);
    });

我已经在我认为代码中需要的地方编写了 cmets,尽管让我解释一下我正在尝试的上下文

  • 我正在从名为 threads 的集合中获取所有成功运行的线程
  • 之后,我尝试使用数据库查询从名为 email 的集合中获取所有电子邮件,我尝试将其输出存储在名为 allEmails 的数组中
  • 如果我 console.log() 它在 .then() 中只是在数据库调用之后给我输出,
  • 我的问题是如何解决这个问题?
  • 我想要一个数组,其中包含另一个数组,每个数组都有来自电子邮件集合的电子邮件集合(每个代表一个线程)

希望我说清楚了,如果还有什么我需要提供的,请成为我的向导并告诉我。

【问题讨论】:

    标签: arrays node.js mongodb promise


    【解决方案1】:

    forEach 块在其内部的任何异步操作返回之前完成。因此,当您 console.log 时,您的 allEmails 数组仍然是空的。

    您需要做的是构建一个用“结果”解析的 Promise 数组,然后将此数组输入 Promise.all(arrayOfPromises),当您的所有 Promise 都解决时,它将解析。

    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() 将是一个更优雅的解决方案。

    希望对你有帮助

    【讨论】:

    • 感谢它对我有用的回复,除了一次更正外,Promise.resolve 是一个方法调用,不应以“new”关键字开头
    • @PreetsinghPanesar 如果对您有用,您应该将答案标记为正确,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2020-03-27
    相关资源
    最近更新 更多