My goal is to implement the solution provided in TypeScript from Stack Overflow:
UPDATE 2 - The issue with the original answer is that it does not support a single deferred. I have made modifications to reproduce the error in his fiddle. http://jsfiddle.net/3h6gwe1x/
UPDATE 1 - It turns out the problem lies in my usage, so I am updating the question to clarify this further.
Initially, I had a method called submitCalculation
which made an AJAX call and I passed a callback handler to be executed upon completion. Everything worked fine until the requirement arose to potentially run multiple submitCalculation
calls and wait for all of them to finish. Thus, I tried wrapping the original call inside a Deferred object as shown below.
const p = function() {
const d = $.Deferred();
try {
that.rble.submitCalculation(
currentOptions,
( errorMessage, result ) => {
if ( errorMessage != undefined ) {
d.reject( { "Options": currentOptions, "ErrorMessage": errorMessage } );
}
else {
d.resolve( { "Options": currentOptions, "Result": result } );
}
}
);
} catch (error) {
d.reject( { "Options": currentOptions, "ErrorMessage": "ReSubmit.Pipeline exception: " + error } );
}
return d;
}
$.whenAllDone( p() ).then(
function( ... successes: { Options: KatAppOptions, Result: RBLResult }[] ) { ... },
function( ... failures: { Options: KatAppOptions, ErrorMessage: string }[] ) { ... } );
During execution of the whenAllDone
method when the following block of code is reached, the parameter arguments
is not structured correctly.
$.when.apply($, deferreds).then(function() {
var failures = [];
var successes = [];
$.each(arguments, function(i, args) {
// If we resolved with `true` as the first parameter
// we have a failure, a success otherwise
var target = args[0] ? failures : successes;
var data = args[1];
// Push either all arguments or the only one
target.push(data.length === 1 ? data[0] : args);
});
if(failures.length) {
return result.reject.apply(result, failures);
}
return result.resolve.apply(result, successes);
});
In the original response's fiddle, the structure of arguments
was in the form of
[ true|false, currentDeferredArguments ][]
. Each element in the array represented the array of parameters resulting from currentDeferred.resolve(true|false, arguments);
.
https://i.sstatic.net/2i2UE.png
However, in my case, the array is flattened and takes the form of
[true|false, currentDeferredArguments]
. So when looping through the arguments using $.each(arguments, function (i, args) {
, my args
do not conform to an 'array'. The initial args
simply represents a boolean value from the currentDeferred.resolve
call, thereby affecting the logic within the loop.
https://i.sstatic.net/1hYdY.png
If I modify my code to test it similarly to the working example provided:
var dfd1 = $.Deferred();
var dfd2 = $.Deferred();
setTimeout(function () {
console.log('Resolve dfd2');
dfd2.reject( { "Options": currentOptions, "ErrorMessage": "Test 2" } );
}, 200);
setTimeout(function () {
console.log('works dfd1');
dfd1.reject( { "Options": currentOptions, "ErrorMessage": "Test 1" } );
}, 100);
$.whenAllDone( dfd1, dfd2 ).then(
How can I properly wrap my original submitCalculation
call to ensure the correct behavior of returning a deferred object for whenAllDone
functionality?