Reputation: 619
i'm using Typescript and jQuery Promises and I am experiencing an error with the following code:
var promiseOne = this.myFunc(1);
var promiseTwo = this.myFunc(2);
$.when(promiseOne, promiseTwo).then((valFromPromiseOne: number, valFromPromiseTwo: number) => //Error here (see below)
{
//Use both return values of the promises...
});
myFunc(value: number): JQueryPromise<number>
{
var dfd = $.Deferred();
setTimeout(function ()
{
dfd.resolve(value);
}, 1000);
return dfd.promise();
}
The error I'm getting is:
Error 5 Supplied parameters do not match any signature of call target:
Call signatures of types '(valFromPromiseOne: number, valFromPromiseTwo: number) => void' and '(value: any) => {}' are incompatible:
Call signature expects 1 or fewer parameters.
I want the function to execute only when both Promises are resolved.
Am I doing somenthing wrong? Is there a different way to achieve what I want?
Thanks
Upvotes: 2
Views: 2854
Reputation: 39045
Although @Jonathan Harrison answer is quite correct, it doesn't cover all possible cases: if the promises are the result of some kind of jQuery ajax call, the received value is not a single value, but an array with three elements: - the expected value - the status of the ajax call - the XHttpRequest object of the ajax call
So, this code fails:
var promiseOne: JQueryPromise<TypeA> = $.ajax(...); // or $.get(), $.post()
var promiseTwo: JQueryPromise<TypeB> = this.myFunc(2);
$.when<any>(promiseOne, promiseTwo).then((
valFromPromiseOne: TypeA, // oops, is an array [TypeA,string, object]
valFromPromiseTwo: TypeB // yeah, it's TypeB
) => {
});
The best solution I've found to get it to compile and work it's a custom type, like this:
type WhenAjaxResponse<T> = [T, string, XMLHttpRequest]
Then, modify the code like this to make it work:
$.when<any>(promiseOne, promiseTwo).then((
valFromPromiseOne: WhenAjaxResponse<TypeA>,
valFromPromiseTwo: TypeB
) => {
// valFormPromise1[0] is of TypeA
}
Upvotes: 2
Reputation: 893
For those still trying to deal with this TypeScript compiler error from the jQuery.d.ts, the generic on $.when will need to be set to 'any' and then you can add typing to the resolving function arguments to resume type safety (and for those fortunate ones... intellisense).
var promiseOne: JQueryPromise<TypeA> = this.myFunc(1);
var promiseTwo: JQueryPromise<TypeB> = this.myFunc(2);
$.when<any>(promiseOne, promiseTwo).then((valFromPromiseOne: TypeA, valFromPromiseTwo: TypeB) => {
//Use both return values of the promises with Type Safety for TypeA and TypeB...
});
Upvotes: 3
Reputation: 23712
You're right, the ".d.ts" seems to be incorrect. But promises in the jQuery way are not Promises/A+ compliant.
The documentation from jQuery:
In the case where multiple Deferred objects are passed to jQuery.when, the method returns the Promise from a new "master" Deferred object that tracks the aggregate state of all the Deferreds it has been passed. The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected. If the master Deferred is resolved, it is passed the resolved values of all the Deferreds that were passed to jQuery.when.
It is not the right definition of the method "then()". According to the Promises/A+ spec, only the first argument should be used:
2/ If onFulfilled is a function: i/ it must be called after promise is fulfilled, with promise's value as its first argument.
Modern browsers implement the spec. The jQuery solution should be avoided, and a compliant polyfill should be preferred. I suggest to read the article from HTML5 Rocks.
Upvotes: 1
Reputation: 619
Finally found out the way to do it. The second parameter has to be optional.
$.when(promiseOne, promiseTwo).then((valFromPromiseOne: number, valFromPromiseTwo?: number) => //valFromPromiseTwo has to be optional
{
//Use both return values of the promises...
});
After this change, it is working fine.
Not sure if it is the right way. But it worked for me.
Upvotes: 4