Big Skinny Big Skinny - 3 months ago 9
JSON Question

JSON array undefined & empty in promise Bluebird

I am using Promise bluebird to process a json array objects from file. The problem arises if I want to store data in a json array (called list) and return this in the final process.
The list is empty/undefined after the return of list or even in the final process. Running the code, I always have 1 value that is not false which trigger the adding/push of the json in the list.

Can you help me with this issue? Below you will find my code.

Thanks in advance !!!

var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));

fs.readdirAsync(dir).map(function (filename) {
return fs.readFileAsync(dir + "/" + filename, "utf8");
}).then(function(result){
var list=[];

result.map(function(row, index){
Promise.coroutine(function*() {
update(row, index).then(function(value){
if (value!=false){
var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
list.push(trade_update);
console.log(JSON.stringify(list)); <-- This works. It gives me data
}
return list;
})
})();
});
console.log('list: ' + JSON.stringify(list)); <-- output: list:[]
return list;
}).finally(function(result){
console.log('Final outcome: '+ ' ' + JSON.stringify(result)); <-- output: Final outcome: undefined
})


With the help of Samuel my code is now:

var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));


function updateOrder(done){
fs.readdirAsync(dir).map(function (filename) {
return fs.readFileAsync(dir + "/" + filename, "utf8");
}).then(function(result){
var list=[];

result.map(function(row, index){
Promise.coroutine(function*() {
update(row, index).then(function(value){
if (value!=false){
var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
list.push(trade_update);
done(list);
}
})
})();
});

//done(list); <--if I put the done callback here, it will give me an empty list. I though once the result.map finished processing all the values give me the end result.
}
}

updateOrder(function(resultList){
console.log('List' + JSON.stringify(resultList));
})


This code give me whole resultList everytime the list has been updated (pushed) now.

I would to receive the resultList at the end once the function updateOrder is finished.

Answer

As noted in the comment. Promise.coroutine is asynchronous so this means that a result is not going to get return straight after your code reaches it. And this pretty much explains the phenomenon you are seeing where the latter print statements you got in the code is suggesting that list is undefined.

What you could do is wrap the entire code you got there in a function, then add a callback function as a parameter for the async functions to invoke when it has finished its duty, together returning the populated list back for later processing.

I have written a pseudo code for your case, unfortunately I couldn't test it on my IDE but the concept is there and it should work.

Consider my pseudo code:

var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));

// Wrap everything you got into a function with a `done` parameter (callback fn)
function doStuff(done) {
  fs.readdirAsync(dir).map(function (filename) {
    return fs.readFileAsync(dir + "/" + filename, "utf8");
  }).then(function(result){
    var list=[];

    result.map(function(row, index){
      Promise.coroutine(function*() {
        update(row, index).then(function(value){
          if (value!=false){
            var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
            list.push(trade_update);
          }
          done(list);
        })
      })();
    });
  }).finally(function(result){
    console.log('File read finish, but this doesnt mean I have finished doing everything!');
  })
}

// call your function and provide a callback function for the async method to call 
doStuff(function(resultList) {
  console.log('list: ' + JSON.stringify(resultList));
  // Continue processing the list data.
});
Comments