Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: async bindings do not return result #22

Open
7flash opened this issue Nov 12, 2023 · 3 comments
Open

bug: async bindings do not return result #22

7flash opened this issue Nov 12, 2023 · 3 comments

Comments

@7flash
Copy link
Contributor

7flash commented Nov 12, 2023

To reproduce run following example:

import { WebUI } from "./deno-webui/mod.ts";

const firstWindow = new WebUI({
    'libPath': './webui/dist/webui-2.dylib',
});

firstWindow.bind('first', async () => {
  return `${new Date()}`
});

firstWindow.bind('second', async () => {
  await new Promise(resolve => setTimeout(resolve, 100));
  return `${new Date()}`
});

try {
  await firstWindow.show(`<html>${new Date().toLocaleTimeString()}<script src="/webui.js"></script></html>`);
} catch (err) {
  console.error(err);
}

await WebUI.wait();
image

As seen in example, running first function returns current date as expected, but unfortunately running second function returns empty string.

@AlbertShown
Copy link
Contributor

I used the debug version of webui, I found out that second() will return a promise object right away, so the webui receives an empty string "" right away. Then later, second() will send back the response ${new Date()} buffer to webui, but it's already late as webui already sent the empty string to UI (Browser).

The solution is making your functions return the wanted response instead of a promise.

firstWindow.bind('second', async () => {
  (async () => {
    await new Promise(resolve => setTimeout(resolve, 100));
  })();
  return `${new Date()}`
});

You can still use promises calls between your functions and app, but the binded one with webui should return the response and not a promise object. This is because C code doesn't wait for the asynchronous... C standard does not have such a thing.

@7flash
Copy link
Contributor Author

7flash commented Nov 14, 2023

Okay gotcha

In your response then we should remove async keyword as well

firstWindow.bind('second', () => {
  (async () => {
    await new Promise(resolve => setTimeout(resolve, 100));
  })();
  return `${new Date()}`
});

Then I am using following approach:

                const nit = nanoid();
                scene = await new Promise(resolve => {
                  window.webuiCallbacks[nit] = resolve;
                  window.webui.executeDeno(denoScript, '{}', nit);
                });
                scene = JSON.parse(scene).result;

Then executeDeno binding:

      const taskId = e.arg.string(2);
            const serializedResponse = JSON.stringify(response)
        .replace(/'/g, "\\'")
      await firstWindow.script(`return window.webuiCallbacks["${taskId}"]('${serializedResponse}')`);

@AlbertShown
Copy link
Contributor

Yes, if that works for you!👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants