3

I am trying to read some file using the JSInterop provided by Blazor.The problem is that even if in .C# i await the method , it seems it does not await it.Thus i can not retrieve the result provided by js.

C#

<input name="start" type="file" onchange="@(async(x)=>await OnChangeS(x))" />

@functions{
    private const string S = "start";

    public async Task OnChangeS(UIChangeEventArgs ev) {
        var str =  await JSRuntime.Current.InvokeAsync<string>("methods.readFile", S);
        Console.WriteLine("From blazor data is:" + (string.IsNullOrEmpty(str) ? "empty" : str));
    }
}

JS

  window.methods = {

    readFile: function (fileName) {

        let reader = new FileReader();
        var file = document.querySelector('input[type=file ][name=' + fileName + ']').files[0];
        var data = null;
        reader.onload = () => {
                data = reader.result;
                console.log("from load data is"+data);

        };
        reader.onloadend = () => {  console.log("from loadend data is"+data);return data };
        reader.readAsText(file);
    }
}

OUTPUT:
Given a sample json file : { "name":"adita","age":33} this is my output order:

WASM: Blazor S:empty

Fread.js:11 from load data is: {
    "name":"adita",
    "age":33
}
Fread.js:14 from loadend data is: {
    "name":"adita",
    "age":33
}

So my question is why is the method not awaited by Blazor ?

5
  • 1
    Your javascript function is not awaiting anything so in what sense is it actually async?
    – Kirk Woll
    Commented Feb 6, 2019 at 14:29
  • I just tried with async having no idea what else to try.It does not return anything with or without async. Commented Feb 6, 2019 at 14:30
  • 1
    Your javascript function is not returning anything at all -- what exactly are you expecting?
    – Kirk Woll
    Commented Feb 6, 2019 at 14:32
  • The events onload and onloadend are fired after the line readAsText so if i return anything after that it won't return anything to Blazor.I thought that it would somehow pipe the return of onloadend to Blazor. Commented Feb 6, 2019 at 14:34
  • 1
    No, async/await in Javascript is pretty much the same as in C#. It doesn't magically hook up to random events to return things. You'll need to use the deferred pattern in Javascript (analogous to TaskCompletionSource in C#) (The link points out it's deprecated, but is more to the point, and you can figure out the modern syntax from the links there)
    – Kirk Woll
    Commented Feb 6, 2019 at 14:44

1 Answer 1

6

I have solved it by wrapping my FileReader result in a Promise.I was not actually sending anything back as @Kirk Woll pointed out.

window.methods = {

    readFile: function (fileName) {
        let reader = new FileReader();
        return new Promise((resolve, reject) => {


            var file = document.querySelector('input[type=file ][name=' + fileName + ']').files[0];
            reader.onerror = () => { reader.abort(); reject("Error parsing file"); };
            reader.onload = () => {
                var data = reader.result;
                console.log("from load data is: " + data);
                resolve(data);


            };
            reader.readAsText(file);
        });
    }
}
3
  • 1
    Interesting, but what if I need to return a value to Blazor ? I can't find a solution for such scenario (At least no easy one). Commented Jul 31, 2020 at 21:05
  • 1
    There's the reverse of the coin too using in Blazor a static method with the JSInvokeable attribute around it. For more info check here. Commented Aug 1, 2020 at 7:51
  • 1
    Thanks brother, this has helped me with my project. Commented May 23, 2021 at 23:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.