'Express js Async

When my code is like this, the rendering is early. I want the above processes to run first and then the rendering process (promise). What should I do to fix the problem?

app.get('/inbox', (req, res) => {
  var messagesList = {
    messages: [],
    subjects: [],
    dates: [],
    from: []
  };
  imaps.connect(config).then(function(connection) {

    connection.openBox('INBOX', (err, box) => {

      console.log(box.messages)
      res.locals.box_messages = box.messages;
      var searchCriteria = ['1:' + box.messages.total];
      var fetchOptions = {
        bodies: ['HEADER', 'TEXT', ''],
      };

      connection.search(searchCriteria, fetchOptions).then(function(messages) {

        messages.forEach(function(item) {

          var all = _.find(item.parts, {
            "which": ""
          })
          var id = item.attributes.uid;
          var idHeader = "Imap-Id: " + id + "\r\n";
          simpleParser(idHeader + all.body, (err, mail) => {

            messagesList.messages.push(mail.html)
            messagesList.subjects.push(mail.subject)
            messagesList.dates.push(mail.date)
            messagesList.messages.push(mail.from.text)
            res.locals.messagesList = messagesList
          })
        })
      })
    })

  })
  res.render('index')
})


Solution 1:[1]

You need to change the forEach for a map and make simpleParser asyncronic so it will wait for it to finish before rendering. Try this code:

app.get("/inbox", (req, res) => {
    imaps.connect(config).then(function (connection) {
        connection.openBox("INBOX", (err, box) => {
            console.log(box.messages);
            res.locals.box_messages = box.messages;
            var searchCriteria = ["1:" + box.messages.total];
            var fetchOptions = {
                bodies: ["HEADER", "TEXT", ""],
            };

            connection.search(searchCriteria, fetchOptions).then(async function (messages) {
                var messagesList = {
                    messages: [],
                    subjects: [],
                    dates: [],
                    from: [],
                };
                for(let i = 0; i < messages.length; i++) {
                    var all = _.find(item.parts, { which: "" });
                    var id = item.attributes.uid;
                    var idHeader = "Imap-Id: " + id + "\r\n";
                    try {
                        await new Promise(function (resolve, reject) {
                            simpleParser(idHeader + all.body, (err, mail) => {
                                if (err) reject(err);
                                messagesList.messages.push(mail.html);
                                messagesList.subjects.push(mail.subject);
                                messagesList.dates.push(mail.date);
                                messagesList.messages.push(mail.from.text);
                                res.locals.messagesList = messagesList;
                                resolve(mail);
                            });
                        });
                    } catch (e) {
                        // handle error
                    }
                };
                res.render("index");
            });
        });
    });
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1