Shared variables in asynchronous function calls - javascript

Is there a basic way to share a variable between two asynchronous functions in Javascript? I'm writing a function for my Parse.com application that sends two queries concurrently and the second waits on the results of the former. I've been using a basic shared boolean and a busy-wait loop, but the loop does not terminate if the boolean value was not set before the start of the loop (but does if it was set before, so the state is in fact being shared across the two callbacks). This makes me think that I need some form of a "volatile" variable but it does not seem that this exists in Javascript, seeing as there are not really threading capabilities/optimizations like this. If it helps, I've added some abbreviated code to help explain what I'm doing:
var firstQueryDone = false;
var firstResultsError = false;
var foundUser;
var foundFollowers;
...
[put some constraints on the query]
...
followersQuery.first({
success: function(followers) {
....
firstQueryDone = true;
},
error: function(error) {
firstResultsError = true;
response.error(error);
}
});
.....
[constraints on new query]
.....
commentsQuery.find({
success: function(comments) {
while(!firstQueryDone && !firstResultsError);
if(!firstResultsError) {
.....
} else {
......
}
},
error: function(error) {
response.error(error);
}
});

I wouldn't use a busy wait-loop. Instead, have both success and error callbacks call store their state then call an external method that handles.
var fComplete = false,
sComplete = false,
didError = false;
#.first(
success: function () {
fComplete = true;
checkMethod();
},
error: function() {
fComplete = true;
didError = true;
checkMethod();
}
);
#.second(
success: function() {
sComplete = true;
checkMethod();
},
error: function() {
sComplete = true;
didError = true;
checkMethod();
}
);
function checkMethod() {
if(fComplete && sComplete) {
if(didError) {
//Handle error
} else {
//Do success here
}
}
}
This way, you don't have a wait loop hogging some resources, and you simply have state changes and onStateChange events.

I think using an object instead of a primitive might help
eg:
var firstQueryStatus = {
qryDone: false,
qryError: false
};

Related

Weird Javascript closure bug

Here is some code.
function callServiceSync(url, obj) {
var result = true;
callServiceOptions(url, obj, function(res){
result = res;
alert("RESULT CB: "+JSON.stringify(result));
}, {async: false});
alert("RESULT POST-CB: "+JSON.stringify(result));
return result;
}
When it runs, the alert box says:
RESULT CB: {"success":true,"data":"dtrombley"}
(that's what the webservice returns, in reality), and then:
RESULT POST-CB: true
Why isn't this assignment to the closure variable working? Am I misunderstanding how JS closures work?
callServiceOptions() is rather longwinded - but the gist of it is that it calls jQuery's $.ajax method with it's last arguments options extended into some default (in this case, async is disable for sync query), and then executes the provided callback.
Is $.ajax() maybe executing something in some kind of way that disables/screws up closures (but I call the cb, not $.ajax()!)? If so, how to fix that?
For completeness (though really this function shouldn't be able to screw things up to my thinking):
function callServiceOptions(url, obj, cb, options) {
optSuccess = options.success;
optError = options.error;
opts = {}
$.extend({},options)
if (!opts.contentType) {
opts.contentType = "application/json";
}
if (!opts.dataType) {
opts.dataType = "json";
}
if (!opts.data && obj) {
opts.data = JSON.stringify(obj);
}
if (!opts.processData) {
opts.processData = false;
}
if (!opts.method) {
opts.method = "POST";
}
opts.error = function(jqXHR, textStatus, errorThrown) {
if (optError) {
optError(jqXHR, textStatus, errorThrown);
}
if (jqXHR.responseText) {
responseObj = JSON.parse(jqXHR.responseText)
if (responseObj && responseObj.message)
cb({
success: false,
message: responseObj.message
})
return
}
cb({
success: false,
message: errorThrown
});
};
opts.success = function(data, textStatus, jqXHR) {
if (optSuccess) {
optSuccess(data,textStatus,jqXHR);
}
cb(data);
};
if (url.charAt(0) == '/') {
url = url.substr(1);
}
opts.url = WEBCTX.getBaseURL() + url;
$.ajax(opts);
}
This is not a duplicate of any question asking how to return a value from an async event. I have a working callServiceAsync() which does that beautifully. I am using synchronous mode, if you aren't familiar with it, please take a pass on this question...
Your function is asynchronous.
While you have created an object that looks like {async: false}, you are passing it as the 4th argument to callServiceOptions so it gets placed in the options variable.
You only access that variable twice (options.success and options.error) so the async property is never used for anything (so $.ajax uses the default value of true).
Adding console.log(opts) just before you call $.ajax(opts); will show this.

Function in while loop executes only once

I am a beginner in javascript, and I'm trying to figure out why my while loop won't actually loop more than once, even though the condition is always met.
I have a function sending an API request:
var get_status = function(trid, count) {
console.log(count);
var req = {
method: 'GET',
url: 'theUrlHere',
headers: {'headers'}
}
$http(req).success(function(data) {
if (data.transaction_status != 'Pending') {
// do something with the data
console.log('true');
return true;
}
else {
console.log('False');
return false;
}
}).error(function(data) {
// show an error popup
console.log('true');
return true;
})
}
};
I want to call this function until it returns true, so I call it this way:
var count = 0;
while (get_status(id, count) === false) {
count += 1;
}
The count variable is just added to see how many times it loops, it stays at 0 even though 'False' is displayed in the console.
Is there some behaviour I am misunderstanding here?
EDIT I understand why this won't work. My intention here is to display an iframe as long as the transaction status is pending. I thought of continually sending a request until the transaction status is something other then 'Pending', but I am aware there are more optimal ways.
Your get_status() function does not return a value. Thus, it's return value is undefined which is falsey so your while() loop stops after the very first iteration.
The return statements you do have in your code are inside of callbacks and have nothing to do with the return value of get_status().
What you are attempting to do is generally not a good design. It appears that you want to run a given Ajax call over and over with no delay until you get the answer you want. This will potentially hammer the destination server.
If you describe the problem you're really trying to solve, we could help come up with a better way to do this. Worst case, you could poll the server with a time delay between requests.
If you wanted to poll every so often, you could do something like this:
function get_status(trid, count) {
var req = {
method: 'GET',
url: 'theUrlHere',
headers: {'headers'}
}
return $http(req).then(function(data) {
return data.transaction_status;
});
}
function poll_status(callback) {
function next() {
get_status(...).then(function(status) {
if (status === "Pending") {
// poll once every two seconds
setTimeout(next, 2000);
} else {
// status is no longer pending, so call the callback and pass it the status
callback(status);
}
}, function(err) {
callback(err);
});
}
next();
}
poll_status(function(result) {
// done polling here, status no longer Pending
});
This is not the correct way to deals with async calls, I'd create a recursive function which will call itself. (in this case get_status should return a promise)
Code
var count = 0, id = 1;//id should be some value
(function myCall(promise){}
promise.then(function(data){
count += 1;
if(data)
myCall(get_status(id, count)); //call function on conditon
});
}(get_status(id, count))
Method(Returning Promise)
var get_status = function(trid, count) {
console.log(count);
var req = {
method: 'GET',
url: 'theUrlHere',
headers: {'headers'}
}
//returning promise here
return $http(req).then(function(response) {
var data = response.data;
if (data.transaction_status != 'Pending') {
// do something with the data
console.log('true');
return true; //resolves the promise
}
else {
console.log('False');
return false; //resolves the promise
}
}, function(data) {
// show an error popup
console.log('true');
return true;
})
}
};
You're trying to return from within an asynchronous callback, which won't work, unfortunately. Instead you'll want a module like async, specifically whilst.
var count = 0;
var outcome = false;
async.whilst(
function () { outcome = false; },
function (callback) {
count++;
// Your code here, setting outcome instead of returning
var req = {
method: 'GET',
url: 'theUrlHere',
headers: {'headers'}
}
$http(req).success(function(data) {
if (data.transaction_status != 'Pending') {
outcome = true;
callback();
}
else {
outcome = false
callback();
}
}).error(function(data) {
outcome = true;
callback();
})
},
function (err) {
// All done!
}
);
But really the behavior you're looking for is probably checking on a status at pre-defined intervals. In this case, adapting the code
var count = 0;
var outcome = false;
async.whilst(
function () { outcome = false; },
function (callback) {
count++;
// Your request stuff.
setTimeout(function () {
callback();
}, 1000); // Waits one second to begin next request
},
function (err) {
// All done!
}
);

Dojo using deferred functions to get data in ajax callback function

I have a function with a return however in the function there is an async request which holds the value that is suppose to be returned by the function. I understand with the nature of async request the function will complete and not return a value while waiting on the async function to complete.
I attempted to use dojo deferred functions to have my function PostInformation() to return a value within the ajax request callback. I am having some issues and i am not sure where my issue is. Under is my code:
Dojo Deferred Function
function PostInformation(){
var hasErrors = false;
var containers = [dijit.byId("container1"), dijit.byId("container2")];
var Employee = {
//data
};
var def = new dojo.Deferred();
def = dojo.xhrPost({
url: 'hello',
content: Employee,
load: function (data) {
formErrors = {
"errors": true,
"fName": "123",
"surname": "456",
"oNames": "789",
"bSurname": "784585"
};
//formErrors = (JSON.parse(data)).formErrors;
$.each(formErrors, function (key, value) {
if (key == 'errors') {
hasErrors = value;
//console.log('hasErrors set to '+value);
}
});
if (hasErrors == true) {
for (var i = 0; i < containers.length; i++) {
var processingContainer = containers[i];
dojo.forEach(processingContainer.getChildren(), function (wid) {
var widgetName = wid.attr('id');
$.each(formErrors, function (key, value) {
if (key == widgetName && value.length > 0) {
var myWidget = dijit.byId(widgetName);
//var wdgName = dijit.byId(widgetName).attr("id");
var myWidgetValue = value;
myWidget.validator = function () {
//console.log('Attribute Name is :' + wdgName + ' Error Value is : ' + myWidgetValue);
//console.log(wdgName + " : "+myWidgetValue);
this.set("invalidMessage", myWidgetValue);
};
myWidget._hasBeenBlurred = true;
myWidget.validate();
}
});
});
}
}
console.log(hasErrors);
def.resolve(hasErrors);
},
error: function(err){
console.log(err);
def.reject(err);
}
});
def.then(function(data){
console.log('In the then function');
//alert('In the def.then and the results is : ' + data);
if(data == true){
return false;
}else{return true;}
},function(err){
return false;
alert('In the def.error and there has been an error ' + err);
});
//return the value of hasErrors here
};
Devdar, you are making heavy wether out of something quite simple. In particular, you don't need to loop through an object to access one of its properties, and the variable hasErrors is not really necessary.
Your code should simplify to something like this :
function PostInformation() {
var $containers = $("#container1, #container2");
var Employee = {
//data
};
return dojo.xhrPost({
url: 'hello',
content: Employee
}).then(function(data) {
data = JSON.parse(data);
var formErrors = data.formErrors;
if(formErrors.errors) {
$containers.each(function(i, c) {
$(c).children().each(function(wid) {
var val = formErrors[wid.id],
myWidget;
if(val) {
myWidget = dijit.byId(wid.id);
myWidget.validator = function() {
this.set("invalidMessage", val);
};
myWidget._hasBeenBlurred = true;
myWidget.validate();
}
});
});
//Send an enhanced error object down the "error" route
throw $.extend(formErrors, {
'message': 'PostInformation(): validation failure'
});
}
//Send the data object down the "success" route
return data;
});
};
PostInformation().then(function(data) {
console.log('PostInformation(): everything went OK');
//access/process `data` here if necessary
//and/or just display a nice "success" message to the user
}, function(err) {
console.error(err.message);
});
Barring mistakes on my part, this code should do everything you want and more. As with your own code, it processes the server's JSON response and returns a Promise, but that's where the similarity stops.
In your code, you seek to return a Promise which is eventually resolved with a boolean to indicate whether or not errors were detected. Whilst this will (if correctly written) meet your immediate needs, it is not the best Promise logic.
In my code, the Promise is resolved only if validation succeeds and rejected if validation fails for whatever reason. Not only is this logically correct behaviour for a Promise (success goes down the success route, and errors go down the error route) but as a bonus should (see note below) also allow you to pass more information to whetever function(s) eventually handle errors. I choose to pass the whole formErrors object enhanced with an error message, thus providing a great deal of freedom in the error handler to display/log/etc as much or as little as is appropriate, and with virtually no assumption inside PostInformation() as to what will happen subsequently. You currently believe that you will only read and act on the boolean formErrors.errors but it could be beneficial to pass as much error data as possible thus allowing yourself the freedom to change your mind at a later date without needing to change anything in PostInformation().
In this regard you can think of PostInformation() as an agent of the server-side service; and like that service, it can be written with incomplete knowledge (or maybe no knowledge at all) of how the (promise of) data/errors it delivers will be used by "consumer code".
NOTE: I have to admit that I'm not 100% familiar with Dojo's Promises, so I'm not sure that a JS plain object can be thrown in the way I indicate. I have found evidence but not proof that it can. For that reason, I am cautious above in saying "your code should simplify to something like this" Anyway, that issue aside, the principle of sending success down the success route and errors down the error route should still apply.
I'd suggest this where you create your own Deferred() object, return it from your PostInformation() function and then register .then() handlers on it so you can pick up the resolve or reject on your own Deferred object that happens inside the PostInformation() function.
The way you had it you were creating your own Deferred() object, but then immediately overwriting it with the xhrPost return result which meant def is now something else and you weren't returning your Deferred from PostInformation() so it can be used outside that function to track the progress.
function PostInformation() {
var hasErrors = false;
var containers = [dijit.byId("container1"), dijit.byId("container2")];
var Employee = {
//data
};
var def = new dojo.Deferred();
dojo.xhrPost({
url: 'hello',
content: Employee,
load: function (data) {
formErrors = {
"errors": true,
"fName": "123",
"surname": "456",
"oNames": "789",
"bSurname": "784585"
};
//formErrors = (JSON.parse(data)).formErrors;
$.each(formErrors, function (key, value) {
if (key == 'errors') {
hasErrors = value;
//console.log('hasErrors set to '+value);
}
});
if (hasErrors == true) {
for (var i = 0; i < containers.length; i++) {
var processingContainer = containers[i];
dojo.forEach(processingContainer.getChildren(), function (wid) {
var widgetName = wid.attr('id');
$.each(formErrors, function (key, value) {
if (key == widgetName && value.length > 0) {
var myWidget = dijit.byId(widgetName);
//var wdgName = dijit.byId(widgetName).attr("id");
var myWidgetValue = value;
myWidget.validator = function () {
//console.log('Attribute Name is :' + wdgName + ' Error Value is : ' + myWidgetValue);
//console.log(wdgName + " : "+myWidgetValue);
this.set("invalidMessage", myWidgetValue);
};
myWidget._hasBeenBlurred = true;
myWidget.validate();
}
});
});
}
}
console.log(hasErrors);
def.resolve(hasErrors);
},
error: function (err) {
console.log(err);
def.reject(err);
}
});
return def.promise;
};
PostInformation().then(function (data) {
console.log('In the then function');
// process data value here which will contain the value you resolved with
}, function(err)
// process an error in the ajax result here
});
I think this is more of an issue with design of the function then.
Since the xHR call is asynchronous, the postInformation shouldn't really return anything unless it's the Deferred object itself. An alternative option is to have postInformation do some sort of event publishing (dojo/topic), that other functions will subscribe to and know how to handle said events.

Testing nested promises with Jasmine

This is working when I run the UI in the browser, but I'm always getting null for the 'd' in my validateAsync method that needs to call the done method to get it back to the save method. I can't figure out how to use the andCallFake (required to spyOn the unique name test), but also get it to return the (jQuery) deferred to call done on.
Hopefully this code will give you enough context to see what I'm trying to accomplish.
validateAsync = function () {
var d,
isValid = true,
isUnique = false;
// validate that name and description are given
if (layout.Name() === '') {
toastr.warning('Layout name is required', 'Layout');
isValid = false;
}
// validate that there are no other layouts of the same type with the same name
d = uiDataService.GetIsLayoutNameUniqueAsync(layout.LayoutId(), layout.Name(), layout.LayoutTypeId())
.done(function (isUniqueResult) {
isUnique = isUniqueResult.toLowerCase() === "true";
if (!isUnique) {
toastr.warning('Layout name ' + layout.Name() + ' must be unique. There is already a layout with this name.', 'Layout');
}
// this is always undefined in my Jasmine tests
d.done(isValid && isUnique);
})
.fail(function (response) {
mstar.AjaxService.CommonFailHandling(response.responseText);
});
return d;
},
save = function () {
validateAsync()
.done(function (isValidResult) {
var isValid = isValidResult.toLowerCase() === "true";
if (!isValid) {
return;
}
// show a toastr notification on fail or success
dataContext.SaveChanges(layout, uiDataService)
.done(function (layoutIdFromSave) {
toastr.success('The layout was saved. Refreshing...');
})
.fail(function () {
toastr.error('There was an error saving the layout.');
})
.always(function () {
// toastr.info('finished');
});
})
.fail(function () {
throw new Error('There was an error validating before save');
});
};
// in uiDataService
getIsLayoutNameUniqueAsync = function (layoutId, layoutName, layoutTypeId) {
return ajaxService.AjaxGetJsonAsync(webServiceUrl + "GetIsLayoutNameUnique?layoutId=" + layoutId + "&layoutName=" + escape(layoutName) + "&layoutTypeId=" + layoutTypeId);
},
// in ajaxService
ajaxGetJsonAsync = function (url, cache) {
return $.ajax({
type: "GET",
url: url,
dataType: "json",
accepts: {
json: "application/json"
},
cache: cache === undefined ? false : cache
});
},
// in a beforeEach
var getIsLayoutNameUniquePromiseSpy = spyOn(mstar.dataService.UiDataService, "GetIsLayoutNameUniqueAsync")
.andCallFake(function () {
spyObj.called = true;
// http://stackoverflow.com/questions/13148356/how-to-properly-unit-test-jquerys-ajax-promises-using-jasmine-and-or-sinon
var d = $.Deferred();
d.resolve('true');
return d.promise();
});
// and a test
it("should show a toastr", function () {
// Act
vm.GetLayout().Name('Test');
vm.GetLayout().Description('Test');
vm.Save();
// Assert
expect(toastr.success).toHaveBeenCalledWith('The layout was saved. Refreshing...');
});
Aligned, I don't know a lot about Jasmine but taking the code on its own merits, it's a lot easier to see what's going on if it's stripped right down to the bare bones.
Greatly simplified, validateAsync() is currently structured as follows :
validateAsync = function () {
...
var d = fn_that_returns_a_promise().done(function() {
...
d.done(boolean);
}).fail(function() {
...
});
return d;
};
which can't be right, because .done() doesn't accept a boolean argument and, whereas I can't say it's definitely wrong, d.done() is not really appropriate inside a d.done() handler (though maybe in different circumstances).
I suggest you want to employ .then() to filter the success case (thus passing on a new promise resolved with your boolean value), while retaining .fail() for the failure case; giving a structure as follows :
validateAsync = function () {
...
return uiDataService.GetIsLayoutNameUniqueAsync(...).then(function(...) {
...
return isValid && isUnique;
}).fail(function(...) {
...
});
};
Thus, save() can be as follows :
save = function() {
validateAsync().done(function(isValid) {
//validation success
if(!isValid) return;
...
}.fail(function() {
//validation failure
...
});
};
Now all you have to do is "join up the dots" (ie. reinsert your own statements etc) and hope I haven't made any mistakes.

How to chain ajax requests?

I have to interact with a remote api that forces me to chain requests. Thats a callback-hell in asynchronous mode:
// pseudocode: ajax(request_object, callback)
ajax(a, function() {
ajax(b(a.somedata), function() {
ajax(c(b.somedata), function() {
c.finish()
}
})
})
It would be much more readable in sync mode:
sjax(a)
sjax(b(a.somedata))
sjax(c(b.somedata))
c.finish()
But Sjax is evil :) How do I do that in a nice not-so-evil and readable way?
You could have a single function which is passed an integer to state what step the request is in, then use a switch statement to figure out what request needs to be make next:
function ajaxQueue(step) {
switch(step) {
case 0: $.ajax({
type: "GET",
url: "/some/service",
complete: function() { ajaxQueue(1); }
}); break;
case 1: $.ajax({
type: "GET",
url: "/some/service",
complete: function() { ajaxQueue(2); }
}); break;
case 2: $.ajax({
type: "GET",
url: "/some/service",
complete: function() { alert('Done!'); }
}); break;
}
}
ajaxQueue(0);
Hope that helps!
Don't use anonymous functions. Give them names. I don't know if you're able to do what I wrote below though:
var step_3 = function() {
c.finish();
};
var step_2 = function(c, b) {
ajax(c(b.somedata), step_3);
};
var step_1 = function(b, a) {
ajax(b(a.somedata), step_2);
};
ajax(a, step_1);
This function should chain together a list of ajax requests, if the callbacks always return the parameters necessary for the next request:
function chainajax(params, callbacks) {
var cb = shift(callbacks);
params.complete = function() {
var newparams = cb(arguments);
if (callbacks)
chainajax(newparams, callbacks);
};
$.ajax(params);
};
You can define these callback functions separately and then chain them together:
function a(data) {
...
return {type: "GET", url: "/step2.php?foo"}
};
// ...
function d(data) { alert("done!"); };
chainajax({type: "GET", url: "/step1.php"},
[a, b, c, d]);
You could also declare the functions "inline" in the call to chainajax, but that might get a little confusing.
Maybe what you can do is write a server-side wrapper function. That way your javascript only does a single asynchronous call to your own web server. Then your web server uses curl (or urllib, etc.) to interact with the remote API.
Update: I've learn a better answer for this if you are using jQuery, see my update under the title: Using jQuery Deffered
Old answer:
You can also use Array.reduceRight (when it's available) to wrap the $.ajax calls and transform a list like: [resource1, resource2] into $.ajax({url:resource1,success: function(...) { $ajax({url: resource2... (a trick that I've learn from Haskell and it's fold/foldRight function).
Here is an example:
var withResources = function(resources, callback) {
var responses = [];
var chainedAjaxCalls = resources.reduceRight(function(previousValue, currentValue, index, array) {
return function() {
$.ajax({url: currentValue, success: function(data) {
responses.push(data);
previousValue();
}})
}
}, function() { callback.apply(null, responses); });
chainedAjaxCalls();
};
Then you can use:
withResources(['/api/resource1', '/api/resource2'], function(response1, response2) {
// called only if the ajax call is successful with resource1 and resource2
});
Using jQuery Deffered
If you are using jQuery, you can take advantage of jQuery Deffered, by using the jQuery.when() function:
jQuery.when($.get('/api/one'), $.get('/api/two'))
.done(function(result1, result2) {
/* one and two is done */
});
Check out this FAQ item on the jQuery site. Specially the callback reference and the complete method.
What you want is data from A to be passed to B and B's data passed to C. So you would do a callback on complete.
I haven't tried this though.
I believe that implementing a state machine will make the code more readable:
var state = -1;
var error = false;
$.ajax({success: function() {
state = 0;
stateMachine(); },
error: function() {
error = true;
stateMachine();
}});
function stateMachine() {
if (error) {
// Error handling
return;
}
if (state == 0) {
state = 1;
// Call stateMachine again in an ajax callback
}
else if (state == 1) {
}
}
I made a method using Promises
// How to setup a chainable queue method
var sequence = Promise.resolve();
function chain(next){
var promise = new Promise(function(resolve){
sequence.then(function(){
next(resolve);
});
});
sequence = promise;
}
// How to use it
chain(function(next){
document.write("<p>start getting config.json</p>");
setTimeout(function(){
document.write("<p>Done fetching config.json</p>");
next();
}, 3000);
});
chain(function(next){
document.write("<p>start getting init.js</p>")
setTimeout(function(){
document.write("<p>starting eval scripting</p>");
next();
}, 3000);
});
chain(function(next){
document.write("<p>Everything is done</p>");
});
Bonus: A ultraligth 138 byte limited A- Promise (that can only resolve - without parameters, and only call the last then-method )
Background:
I made this for node.js at the point where it dose not have promises ATM. I didn't want a complete full blown Promise library that I was dependent on and had to include in my package.json, I needed it to be fast and light and do mostly one thing only. I only needed it for one thing (chaining things like you want to)
function Q(a,b){b=this;a(function(){b.then&&b.then();b.then=i});return b}function i(a){a&&a()}Q.prototype={then:function(a){this.then=a}};
How?
// Start with a resolved object
var promise = new Q(function(a){a()});
// equal to
// var promise = Promise.resolve();
// example usage
new Q(function(resolve){
// do some async stuff that takes time
// setTimeout(resolve, 3000);
}).then(function(){
// its done
// can not return a new Promise
}); // <- can not add more then's (it only register the last one)
and for the chainable queue method
// How to setup a chainable queue method with ultraligth promise
var sequence = new Q(function(a){a()});
function chain(next){
var promise = new Q(function(resolve){
sequence.then(function(){
next(resolve);
});
});
sequence = promise;
}
The complete callback is what you're looking for:
$.ajax({
type: 'post',
url: "www.example.com",
data: {/* Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. */},
success:
function(data) {
/* you can also chain requests here. will be fired if initial request is successful but will be fired before completion. */
},
complete:
function() {
/* For more a more synchronous approach use this callback. Will be fired when first function is completed. */
}
});

Categories

Resources