简体   繁体   中英

Iterate save in Node.JS across an array

I couldn't use a simple for loop because request.save is a function. So I tried forEach. It works perfectly! Until I add in the request.save part and I get the following error message that breaks my app.

Error: Can't set headers after they are sent.

exports.submit = function (req, res) {


  Person.find({
      cellPhone: req.body.phone
  }).exec(function (err, people) {
      people.forEach(saveRequest);
  }

  function saveRequest(item, index) {

       var request = new Requests();
       request.start = req.body.start.value;
       request.finish = req.body.finish.value;
       request.phone = req.body.phone;
       request.offDay = req.body.date;

       request.user = people[index]._id;
       request.name = people[index].name;
       request.group = people[index].group;

       request.save(function (err) {
          if (err) {
             console.log('request.save');
             return res.status(400);
           } else {
             // Remove sensitive data before login
             //user.password = undefined;
             //user.salt = undefined;
             console.log(request);
             res.json(request);
           }
       });
  }
});

The problem is when you perform the .save() you pass an anonymous function that complete the response in case of error.

So you finish on the first save event error.

You should complete the response outside the save callback.

Maybe use events to sync your code, or better the generators.

Before your forEach loop:

let savedResponses = [];
let savedErrors = [];
...

Then your savedRequest:

function saveRequest(item, index) {

    var request = new Requests();
    request.start = req.body.start.value;
    request.finish = req.body.finish.value;
    request.phone = req.body.phone;
    request.offDay = req.body.date;

    request.user = people[index]._id;
    request.name = people[index].name;
    request.group = people[index].group;

    request.save(function (err) {
        if (err) {
            console.log('request.save error');
            savedErrors.push(err);
            // return res.status(400);
        } else {
            // Remove sensitive data before login
            //user.password = undefined;
            //user.salt = undefined;
            console.log(request);
            savedResponses.push(request);

        }
    });

}

Then after the forEach loop, you should wait the end of the asynchronous staff in the .save() callbacks.

You could use the event package or the generators or the promise pattern.

It depend on the version of your node.

When you have the code synched you could just complete your response checking for errors first:

if (savedErrors.length > 0) {
    res.status = 400;
    // ... report errors
}

Or just complete the response with the savedResponses .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM