I have created a web api method that carries out calculations using a json object I post to the method. My understanding is that a jquery post is asynchronous? Assuming this is so, I'd like to be able to chain together multiple calls to the js function that invokes this api method because certain calls are order-critical.
There are 80 calls to this asynchronous api method in a row. I don't want to do:
asyncMethodCall1(myParams).then(asyncMethodCall2(myParams).then...))
...
as there is no need to chain them like this as none of them depend on the other and can all run simultaneously. However at the end I need to do some other calculations that DO depend on the previous results having finished.
Is there a way of doing a sort of group of calls followed by a "then"? Is it simply a case of having something like:
mySynchronousFunction(params).then(function() {...do other calcs});
function mySynchronousFunction(params) {
asyncmethodcall1(myparams);
asyncmethodcall2(myparams);
asyncmethodcall3(myparams);
...
asyncmethodcall76(myparams);
}
or do I need to have a "setTimeOut" in there somewhere? JavaScript is something I'm tryign to learn and it's all a bit odd to me at the moment!
EDIT 1
Well I'm stumped.
I know it's a fundamental lack of understanding on my part that's causing the problem but it's very hard to find basic introductory stuff that someone coming from a synchronous language can follow and understand. Currently a resource I'm working through is this one and it seems to make some sense but it's still not sinking in: http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics
Currently I have this:
$.when(
individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e),
individualImpactCalc('byWeightAndFactor', 'Water', articleResults().material_Water),
individualImpactCalc('byWeightAndFactor', 'pH', articleResults().material_pH),
...lots of other calls in here...
).then(function () {
//do calculation totalling
alert("I'm done!");
}).fail(function() {
alert("Argh! I failed!");
});
...and it simply doesn't work as I want it to. I never get an alert showing. The impact calculations are done, the observables are updated, my page values change, but no alerts.
What am I fundamentally missing here?
Edit 2
What I was fundamentally missing was the difficulty in debugging chained promises! It actually was working once I cured a hidden reference error that wasn't bubbling up. Lots of painstaking stepping through javascript finally found it.
Just to add in another element to the mix of answers, I used the Q library as that was what is used in Durandal/Breeze anyway and it's just easy to keep the code consistent. I tried it with $.when and it worked just as well. I tried it with Promise and it failed with "Promise is not defined".
My working Q implementation:
var calcPromise = Q.all([
individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e),
individualImpactCalc('byWeightAndFactor', 'Water', articleResults().material_Water),
individualImpactCalc('byWeightAndFactor', 'pH', )]);
return calcPromise
.then(calcsDone)
.fail(calcsFailed);
function calcsDone() {
alert("all calcs done");
}
function calcsFailed() {
alert("Argh! Calc failure...");
}