Reputation: 65510
I have this code:
loadData: function() {
return new Promise(function(resolve, reject) {
$.ajax({ dataType: 'json', url: url1}).done(function(r) { resolve(r); });
});
},
drawGraph: function(stats) {
// do stuff with the stats
},
// lower down...
this.loadData().then(this.drawGraph);
It works fine. But now I want to make another Ajax call and combine data the two results, before calling drawGraph
.
This is what I've tried:
loadSiteTraffic: function() {
return new Promise(function(resolve, reject) {
return $.ajax({ dataType: 'json', url: url1}).done(function(r) { resolve(r); });
}).then(function(results1) {
return $.ajax({ dataType: 'json', url: url2}).done(function(r) { resolve(r); });
}).then(function(results1, results2) {
return results1 + results2;
});
}
But now I'm getting Uncaught ReferenceError: resolve is not defined
on the second time that resolve
appears.
I guess this is something about how I pass resolve
to the second call.
But I want to hang on to the results of the first call. What should I be doing instead?
Maybe I need to make two separate loadData
functions, call one from the other, and somehow combine the results in a third function...?
Upvotes: 0
Views: 1046
Reputation: 13346
You can create a generic method that wrap the ajax call and returns promise:
load: function(param) {
return new Promise(function(resolve, reject) {
$.ajax(param).done(function(r) { resolve(r); });
});
},
loadData: function() {
var res1;
return this.load({ dataType: 'json', url: url1}).then(function(results1) {
res1 = results1;
return this.load({ dataType: 'json', url: url2});
}).then(function(res2) {
return res1 + res2;
});
},
drawGraph: function(stats) {
// do stuff with the stats
},
// lower down...
this.loadData().then(this.drawGraph);
If the second call doesn't depends on the first call, you can use promise.all:
load: function(param) {
return new Promise(function(resolve, reject) {
$.ajax(param).done(function(r) { resolve(r); });
});
},
loadData: function() {
return Promise.all([
this.load({ dataType: 'json', url: url1}),
this.load({ dataType: 'json', url: url2}),
]).then(function([results1, results2]) {
return results1 + results2;
});
},
drawGraph: function(stats) {
// do stuff with the stats
},
// lower down...
this.loadData().then(this.drawGraph);
Upvotes: 0
Reputation: 44376
First, you need to make a general function that makes a promise from your AJAX calls:
const ajaxPromise = url =>
new Promise(resolve =>
$.ajax({ dataType: 'json', url}).done(r => resolve(r); );
);
Now, you can either just invoke both of them:
Promise.all(ajaxPromise(url1),
ajaxPromise(url2))
.then([results1, results2]) => results1 + results2);
or if you really need them chained:
ajaxPromise(url1)
.then(results1 =>
ajaxPromise(url2)
.then(results2 => results1 + results2));
Upvotes: 0
Reputation: 6074
I normally do my ajax calls like this:
$.ajax({
dataType: 'json',
url: url1,
success: function (res1) {
// Do stuff with res1
$.ajax({
dataType: 'json',
url: url2,
success: function (res2) {
// Do stuff with res2
return res1 + res2;
),
});
),
});
This way the calls are "waiting" for each other to finish.
Upvotes: 0
Reputation: 23859
What you're currently doing is an overkill. You don't need the the Promise constructor wrapper over $.ajax
call (unless you're doing some complex async operations underneath), as $.ajax
already exposes promise-like then
handlers.
Additionally, both of your calls don't depend on each other. So you can simultaneously make both the calls and combine the results using $.when
:
loadSiteTraffic: function() {
return $.when({
result1: $.ajax({ dataType: 'json', url: url1}),
result2: $.ajax({ dataType: 'json', url: url2})
})
.then(function(resp) {
return resp.result1 + resp.result2;
});
}
In your code, you encounter the undefined resolve
as it is not available to the then
callback.
Upvotes: 2