I'm having problems sending an AJAX call after the other while looping and array of objects. The code is the following
var def = true;
$.each(urls, function(index, val) {
var postResult = $.Deferred();
link = 'http://myurl.com' + val.aslug + '/' + val.slug;
$.when(def).then(function(){
$.post('https://graph.facebook.com ', {id : link, scrape : 'true' }, function(data, textStatus, xhr) {
}).always(function(){
postResult.resolve(5);
});
});
def = postResult;
});
The problem is the first and the second call they are ok. But the third call and the following are the same as 2nd call :/ I think the each is not changing to the next object
The easiest way in this case will be: move variable link assignment inside of the "when-then" construction.
var def = true;
$.each(urls, function(index, val) {
var postResult = $.Deferred();
$.when(def).then(function(){
var link = 'http://myurl.com' + val.aslug + '/' + val.slug;
$.post('https://graph.facebook.com ', {id : link, scrape : 'true' }, function(data, textStatus, xhr) {
}).always(function(){
postResult.resolve(5);
});
});
def = postResult;
});
You got this issue because of JS asynchronous ability. $.each() - loop simply doesn't wait when your "deferred piece of code" will be run. It loops thru your array and creates a queue of tasks which will be executed.
Also you may consider to use $.AJAX
with option async:False
, instead
Your instinct is correct - the biggest problem is that you don't want to create a function within a loop. By the time $.when
resolves for the second time, your link
variable inside that closure will no longer reference the correct values. That's why you are getting a bunch of calls to the same url.
In addition, to create a sequence of promises, you are going to want to use something like this: https://github.com/kriskowal/q#sequences (not sure if jQuery promises has a comparable feature)
Example code:
// not sure if this is necessary
// haven't used jQuery promises much
var result = $.when(true);
mapUrlsToPosts(urls).forEach(function(f) {
result = result.then(f);
});
function mapUrlsToPosts(urls) {
return urls.map(function(url) {
// create a function that when executed will make a request to the desired url
return post.bind(null, url);
});
}
function post(val) {
var link = 'http://myurl.com' + val.aslug + '/' + val.slug,
postResult = $.Deferred(),
params = {
link: link,
scrape: 'true'
};
$.post('https://graph.facebook.com ', params, function(data, textStatus, xhr) {
}).always(function(){
postResult.resolve(5);
});
return postResult;
}
EDIT: By the way, all this can be made much simpler if you don't need to wait for the previous request to finish before making the next. Most of the complexity here comes from queueing the requests.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.