Reputation: 355
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.
Upvotes: 1
Views: 3727
Reputation: 87
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);
}
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
Upvotes: 1
Reputation: 23049
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.
Upvotes: 1