0

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": []
}
NobleUplift
  • 5,631
  • 8
  • 45
  • 87
  • hmm... are you returning anything from the reduce? I don't see a return – Kevin B Sep 29 '17 at 21:30
  • Would I need to change from using arrow functions => to an actual callback function? Only issue there is that I have some `this.` references inside, but I'll replace them with variables and give that a go. Also just noticed that I published my answer too soon. Whoops. – NobleUplift Sep 29 '17 at 21:31
  • no, an arrow function is fine if it's warranted. – Kevin B Sep 29 '17 at 21:32
  • Can I return from an arrow function without triggering a return in the parent function? I'll probably convert this answer to the *working* code, and then ask how to get what's not working, working, instead of showing what I'm trying right now. – NobleUplift Sep 29 '17 at 21:37
  • there must be code missing... you should be getting a syntax error on `results.push` – Kevin B Sep 29 '17 at 21:37
  • and, yes, returning from a callback is fine, it won't return from the parent function. – Kevin B Sep 29 '17 at 21:40
  • Yes, I was trying to simplify my code as much as possible to make it easier to read, but in fact just made a complete mess of things and a nonsensical question :| Anyway @KevinB, I've updated it with *working* code so that you can see what's functional and what's not. – NobleUplift Sep 29 '17 at 21:47
  • well, i still don't see what you're returning form the map callback (it also needs a return so that it knows what to put in the array, just like reduce.) ideally it should be returning a promise that completes when whatever async action is required for that item is complete. for example, `return Database.getInstance()...` or `return transform.baseExtract()` – Kevin B Sep 29 '17 at 21:51
  • 1
    To help answerers, and improve your understanding of your own code, I suggest getting rid of most of the code inside your `map()` call and replacing it with `return promise.resolve({your expected data goes here})`. Once you figure that out, then add the other code back (preferably by moving it into functions that you call from `map()` - there is way too much code here!). – stone Sep 29 '17 at 21:57
  • @KevinB, thanks! I looked back at my linked question and sure enough, I'm missing those two returns. Mind if I edit it into skypecakes answer since I can only accept one of you? Thank you both for your help late on a Friday workday. – NobleUplift Sep 29 '17 at 22:27

1 Answers1

2
  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);

NobleUplift
  • 5,631
  • 8
  • 45
  • 87
stone
  • 8,422
  • 5
  • 54
  • 66
  • I was creating a for loop, but doh! ```array.filter``` is a much better idea. I did a lot of ```usort```/```uasort``` in PHP, but I guess I'm still in a functional programming mindset. – NobleUplift Sep 29 '17 at 22:02