Conversion from es5.Promise<TResult> to Task<TResult> with ToTask() returns an Array object instead of TResult
YImhof opened this issue · 3 comments
In case of conversion from Promise
to Task
returning a result, the getAwaitedResult
method returns the result encapsulated in an array.
For example, the following code never logs the resulting Response
object, as response.status
is undefined
.
internal class Program
{
static async Task Main(string[] args)
{
RequestInit request = new RequestInit()
{
keepalive = true
};
Response response = await fetch($"{window.location.href}any/call", request).ToTask();
if (response.status == 404)
console.log(response);
}
}
Part of the transpiled code to JS:
switch ($s) {
case 0: {
request = { keepalive: true };
$t1 = System.Threading.Tasks.Task.fromPromise(fetch(System.String.format("{0}any/call", [window.location.href]), request));
$s = 1;
if ($t1.isCompleted()) {
continue;
}
$t1.continue($asyncBody);
return;
}
case 1: {
$tr1 = $t1.getAwaitedResult();
response = $tr1;
if (response.status === 404) {
console.log(response);
}
}
}
Variable $tr1
is an array of length 1 having the Response
object at index 0.
So perhaps, the line response = $tr1;
should be response = $tr1[0];
?
For a complete information, you have to know that i am trying to create a h5 proxy for an existing TS class that returns promises, doing something similar to the above code, like the following:
[External]
[Name("idProvider")]
internal static class IdProvider
{
[Template("System.Threading.Tasks.Task.fromPromise({this}.isLoginRedirect())")]
public static extern Task<bool> IsLoginRedirect();
}
Calling IsLoginRedirect
makes a call to the server getting an OIdC configuration to be applied, and so is asynchrone.
In both cases, getAwaitedResult
returns the unexpected array object.
Hi @YImhof,
The issue seems to be from the implementation of fromPromises:
promise.then(function () {
tcs.setResult(handler ? handler.apply(null, arguments) : Array.prototype.slice.call(arguments, 0));
}, function () {
tcs.setException(errorHandler ? errorHandler.apply(null, arguments) : new H5.PromiseException(Array.prototype.slice.call(arguments, 0)));
}, progressHandler);
As you can see, arguments is the calling arguments from the function on promise.then, and it is just passed as the result to the Task.
That's why the signature of Task.FromPromise is
public static extern Task<object[]> FromPromise(IPromise promise);
I think the right way for you to use the template should be instead to pass the argument number you want from the response in the "handler" argument:
[External]
[Name("idProvider")]
internal static class IdProvider
{
[Template("System.Threading.Tasks.Task.fromPromise({this}.isLoginRedirect(), 0)")] // <<<<< Add 0 here
public static extern Task<bool> IsLoginRedirect();
}
Hello @theolivenbaum,
Thanks a lot for the feed-back and the solution. I tried it and the problem is solved.
Sorry that I missed the point of the input arguments pass-through.
No worries, I was also not aware of it 😅