NobleUplift NobleUplift - 2 years ago 137
Node.js Question

How do I skip a callback when running .map in JavaScript/Node.js?

Kind of a sequel to this question, I need to accept multiple objects in a POST request and then for each object process it, save it, and then return the saved object to the frontend (so that the client can see which columns were successfully edited).

When I use .map, it does save to the database and I can confirm this. However, I have two problems:


  1. It does not execute
    res.locals.retval.addData(dtoObject);
    correctly, and my returning payload has no data transfer objects inside of it.

  2. My object validation cannot be done inside of the callback of
    map
    . I initially tried
    reduce
    , but that didn't work at all and just saved all the same values to each database object. How can I exclude invalid JSON objects while I'm mapping them?

    var jsonObjects = req.body;
    //for (var n in req.body) {
    var promises = jsonObjects.map((jsonObject) => {
    var transform = new Transform();

    // VALIDATION OF jsonObject VARIABLE IS HERE

    if (jsonObject.id == 0) {
    var databaseObject = Database.getInstance().getModel(objectName).build(jsonObject);

    transform.setNew(true);
    transform.setJsonObject(jsonObject);
    transform.setDatabaseObject(databaseObject);

    transform.baseExtract()
    .then(() => transform.extract())
    .then(() => transform.clean())
    .then(() => transform.getDatabaseObject().save())
    .then(function(data) {
    // PROCESSING DATA
    }).catch((e) => {
    // ERROR
    });
    } else {
    var queryParameters = {
    where: {id: jsonObject.id}
    };
    console.log("Query parameters: ");
    console.log(queryParameters);
    Database.getInstance().getModel(objectName).findOne(queryParameters).then((databaseObject) => {
    transform.setJsonObject(jsonObject);
    transform.setDatabaseObject(databaseObject);
    })
    .then(() => transform.baseExtract())
    .then(() => transform.extract())
    .then(() => transform.clean())
    .then(() => transform.getDatabaseObject().save())
    .then((data) => {
    // PROCESSING DATA
    }).catch((e) => {
    // ERROR
    });
    }
    });

    Promise.all(promises)
    .then((results) => {
    return next();
    }).catch((e) => {
    throw e;
    });



Here's the resulting payload:

{
"errors": [],
"warnings": [],
"data": []
}

Answer Source
  1. As @KevinB said in the comments, you are missing the return calls inside of your arrow functions so the database saves are going through because they are part of the Promise chain, but pushes to the response are stalled waiting for the return, and then the Express.js call resolves before the Promises do. Add return Database.getInstance() and return transform.baseExtract() to your code to fix this.
  2. Use Array.prototype.filter() to remove elements you want to ignore since you won't ever need to execute Promises on them, then call Array.prototype.map() on the resulting array. If you don't want to use the arrow functions, you can specify this as a parameter to filter and map:

    jsonObjects.filter(function(jsonObject) {

    }, this);

    var promises = jsonObjects.map(function(jsonObject) {

    }, this);

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download