I'm currently struggling to make an interop call work because I can't synchronously wait for a Promise in javascript.
Before you think about closing this as duplicate, note that I have done some searching and I understand that it says everywhere it's not possible to synchronously wait for a Promise. Once async, always async. Source(s): How to wait for a JavaScript Promise to resolve before resuming function?, How can I synchronously determine a JavaScript Promise's state?, Call An Asynchronous Javascript Function Synchronously, Can i force a promise to resolve synchronously (reddit).
I've seen this generator approach but I have not been able to implement it correctly, so maybe there's some potential left.
For now synchronously waiting for the Promise doesn't seem possible. Now I'd like to know what I can do instead in my situation.
Note: I think I should mention that I don't know javascript all too well.
In my case I cannot rethink my design entirely because I don't control the consumer nor the the actual interop-call. The only thing I have full control over is the object I hand to the consumer.
Here's a basic example of my issue (jsfiddle, code below).
I have a filter function that accepts or rejects an index. That function is a member of a config object which gets passed to the consumer (I have full control over the config object).
The consumer uses this filter later on to determine if an index should be filtered out or not. I have no control over the consumer and the consumer may use the filter at any time without me having an influence on that.
Now if I just use a normal non-async function in my config object, everything works great. But I'd like to forward my call to C#, use a filter there and return the result to the consumer.
I'm using blazor and the interop call returns a promise (there's also a synchronous method but that doesn't work for all blazor variants) so I have to await it to get the value. To await something I have to make my function async and that means it will also return a Promise. Now I'm in this once async, always asnyc. The consumer just checks if the value returned by the filter is truthy and because a Promise is an object, it will be truthy no matter what it will resolve to.
var normalFilter = index => index % 2 == 0;
var asyncFilter = async index => {
// same filter but returns after 500ms. In the actual application the result is returned from a c# function
return await fakeInteropCall(index, normalFilter);
}
var conf = {
filter: normalFilter // if you put asyncFilter here, everything will be filtered
};
fakeConsumer(conf); // call the consumer with the config. Note that in the actual application, the consumer just stores the filter and uses it later. I can't influence when the filter gets executed.
// I can't change this consumer, it's actually chart.js
function fakeConsumer(config) {
for (let i = 0; i < 5; i++) {
if (config.filter(i)) {
console.log("filtered " + i);
} else {
console.log(i);
}
}
}
// I can't change this interop call, it's from blazor and only the async version works on all variants
function fakeInteropCall(index, filterFunc) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(filterFunc(index));
}, 500);
});
}
What can I do to ensure that this consumer gets the correct values?
The last resort would be to use the non-async interop call and only support half the blazor variants but that would be very unfortunate.