1

I am newbie to Node.js and I am struggling with asynchronous calls.

In this below code I have an array of feeds for example(1,2,3..). each feed can contain multiple images and now i want to delete the images from the folder and from database.

What i have done so far:

for(var i=0; i<feedArr.length; i++){
    var feedId = feedArr[i].feedid;
    var listFeedImageQuery  = "select imageUrl from feedImages where feedId='"+feedId+"'";
    var deleteFeedImagesQuery = "delete from feedImages where feedId='"+feedId+"'";
    model.client.query(listFeedImageQuery,function(err,result){
        if(result.rows.length > 0){
            for(var j=0; j<result.rows.length; j++){
                fs.unlink(result.rows[j].imageurl, function(err) {
                    if(err)
                        console.log(err);
                });
            }
            model.client.query(deleteFeedImagesQuery,function(err,result){
                if(err)
                    console.log(err)
                else
                    console.log(feedId +' were removed'); // last feedId only gets removing from database
            });
        }   
    });
}

Here I am able to delete the images from the image storage folder, but I am unable to delete the records from the database. Only the last feed record is getting deleted. The rest of the feedImage records are in database.

I researched something about async modules, but i don't know how to apply it to this issue.

3
  • You do know that it has a cyclical processing by one thread only don't you. Why on earth would you want to write synchronous function. Commented Mar 16, 2016 at 14:22
  • yes i know that, but in some situation its frustrating, do u know how to solve this. Commented Mar 16, 2016 at 14:28
  • Possible duplicate of The best pattern for handling async looping in Node.js Commented Mar 16, 2016 at 14:29

2 Answers 2

1

this is a common problem when switching to callback framework from the "standard" one.

This is how it works, first it synchronously run this

for(var i=0; i<feedArr.length; i++){
    var feedId = feedArr[i].feedid;
    var listFeedImageQuery  = "select imageUrl from feedImages where feedId='"+feedId+"'";
    var deleteFeedImagesQuery = "delete from feedImages where feedId='"+feedId+"'";
    model.client.query(listFeedImageQuery,function(err,result){
        //to be executed later
    });
}

The method model.client.query is pushed with each cycle to the "stack of asynchronous calls", therefore in the moment when the all these queries are executed, the feedId is equal to feedArr[feedArr.length-1].feedid

One simple workaround is to wrap it around methods with parameter and then call them immediately.

for(var i=0; i<feedArr.length; i++){        
    (function(feedId) {
       var listFeedImageQuery  = "select imageUrl from feedImages where feedId='"+feedId+"'";
       var deleteFeedImagesQuery = "delete from feedImages where feedId='"+feedId+"'";
       model.client.query(listFeedImageQuery,function(err,result){
           //to be executed later
       });
    })(feedArr[i].feedid);
}

Now it should work.

Sign up to request clarification or add additional context in comments.

Comments

1
for (var i = 0; i < 10; i++) {
  console.log('sync', i);   
  setTimeout(function () {
    console.log('wrong async', i)
  }, 1);
}


for (var i = 0; i < 10; i++) {  
  setTimeout((function (j) {
    console.log('right async', i)
  })(i), 1);
}

enter image description here

Figure it out, maybe you will know where you was wrong.


For your issue, you can extract the async code as a function, like this:

function deleteImages(feedId) {
    var listFeedImageQuery  = "select imageUrl from feedImages where feedId='"+feedId+"'";
    var deleteFeedImagesQuery = "delete from feedImages where feedId='"+feedId+"'";
    model.client.query(listFeedImageQuery,function(err,result){
        if(result.rows.length > 0){
            for(var j=0; j<result.rows.length; j++){
                fs.unlink(result.rows[j].imageurl, function(err) {
                    if(err)
                        console.log(err);
                });
            }
            model.client.query(deleteFeedImagesQuery,function(err,result){
                if(err)
                    console.log(err)
                else
                    console.log(feedId +' were removed'); // last feedId only gets removing from database
            });
        }   
    });
}

for(var i=0; i<feedArr.length; i++){
    var feedId = feedArr[i].feedid;
    deleteImages(feedId);
}

For the more complex issue, if you don't want the callback hell, try async or bluebird

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.