sam sam - 2 months ago 14
Node.js Question

then of promise not waiting for result to return

Following are the functions in node.js using promise.

exports.getDetailsByUserId = function(req,res) {
getUserDetails(req, res) // function to get user details
.then(function (Details) {
var allpromises = Details.map(getStatus); //get and update the status of user
return allpromises
})
.then(function (promises) {
var orderresult =[];
Q.allSettled(promises)
.then(function (allpromises) {
orderresult.push(allpromises);
})
return orderresult;
})
.then(function (result) {
getUserDetails(req, res)//again calling get user details so that i will get modified result
.then(function (data) {
res.json({
"User" : data
})
})
})
.catch(function (error) {
console.log(error);
res.status(200).json({
"Message": error
})
})
}

var getStatus = function (data,req) {
var deferred = Q.defer();
requestify.post('http://example.com', {
"data": [{ "Number": No }]
})
.then(function (response) {
response.getBody();
response.body;
var Status = JSON.parse(response.body);
var Details = { "_id": data._id, "Status": Status.status[0] };
return OrderDetails;
})
.then(function (DetailsData){
var req = { body : { Details :DetailsData} };
updateDetails(req).then(function (data) {
deferred.resolve;
})
})
.catch(function (error) {
deferred.resolve(error);
});
return deferred.promise;
}


The
getUserDetails
function gets details of user first time, then
getStatus
calls another API and updates related user status. To this point every thing is working fine.

I need to call
getUserDetails
a second time to get updated results, but it does not give update results. Maybe it gets called before updating the status? What might be wrong with the code so that it will execute after
Q.all
?

Thank you.

Answer
var orderresult =[];
Q.allSettled(promises)
.then(function (allpromises) {
    orderresult.push(allpromises);
})
return orderresult;

You fell for the classical mutation in asynchronous callback problem. The then callback is asynchronous, and the orderresult will not contain the allpromises array when it's returned. To make something wait for the promise, you have to return it.

In any case, you should simplify your code to

getUserDetails(req, res)
.then(function (details) {
    var allpromises = details.map(getStatus);
    return Q.allSettled(allpromises); // just call it here already and return a promise
})
.then(function (allpromiseresults) {
    var orderresult = [allpromiseresults]; // not sure what this is good for
    return orderresult;
})
.then(function (result) { // given that you don't use the `result` anyway
    return getUserDetails(req, res);
}).then(function (data) {
    res.json({                             
        "User" : data
    })
}, function (error) {
    console.log(error);
    res.status(200).json({
        "Message": error
    })
});

and in getStatus you should avoid the deferred antipattern:

function getStatus(data,req) {
    return requestify.post('http://example.com', {
        "data": [{ "Number": No }]
    })
    .then(function (response) {
        response.getBody(); // ???
        var status = JSON.parse(response.body);
        var details = { "_id": data._id, "Status": Status.status[0] };
        // no `OrderDetails`, no `DetailsData`

        var req = {body: {Details: details}};
        return updateDetails(req) // probably "getStatus" should be called "updateStatus"
    });
}
Comments