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

Promise not resolving, if resolve() invoked from C# callback function #1576

Open
Dubiy opened this issue Jul 5, 2023 · 6 comments
Open

Promise not resolving, if resolve() invoked from C# callback function #1576

Dubiy opened this issue Jul 5, 2023 · 6 comments

Comments

@Dubiy
Copy link

Dubiy commented Jul 5, 2023

Version used

v3.0.0-beta-2049

Describe the bug

Promise not resolving, if resolve() invoked from C# callback function.

To Reproduce

GIST: https://gist.github.com/Dubiy/a761662f95341bc530574dec9f29e02a

Or code:

using Jint;
using UnityEngine;
using System;
using System.Threading.Tasks;

public class RunJs : MonoBehaviour
{
    private static Engine engine;
    
    void Start()
    {
        engine = new Engine();
    
        engine.SetValue("console",typeof(Debug));
        engine.SetValue("setTimeout", new Action<Action<int>, int>(setTimeout));


        engine.Execute(@"
            function delayResolve(delay) {
                return new Promise(function(resolve) {
                    setTimeout(function() {
                        console.log('onTimeout');
                        resolve('success');
                    }, delay);

                    // resolve('works, if not called from C# inoked function')
                });
            }

            delayResolve(1000)
                .then(res => {
                    console.log('resolved: ' + res);
                })
                .catch(res => {
                    console.log('rejected: ' + res);
                })
            ;
        ");

        void setTimeout(Action<int> callback, int delay)
        {
            Task.Delay(delay).ContinueWith(_ => callback(delay));
        }
    }
}

Expected behavior

onTimeout
resolved: success

Actual behavior

onTimeout
@lahma
Copy link
Collaborator

lahma commented Jul 5, 2023

Jint doesn't support multi-threading and that's what your Task.Delay is doing.

@Dubiy
Copy link
Author

Dubiy commented Jul 5, 2023

Is there some alternative solution how to resume js code execution after c#? As far I understrand it's quite popular problem (fetch, setTimeout, etc...)

@lahma
Copy link
Collaborator

lahma commented Jul 5, 2023

I think this would need some investigation and hopefully a PR that would both include tests and a remedy 😉

@Looooong
Copy link

Looooong commented Sep 9, 2023

For me, Promise doesn't even resolve on JS side:

new Promise(function (resolve) {
  log('Promise!')
  resolve(null)
}).then(function () {
  log('Resolved!')
})

Expected output:

Promise!
Resolved!

Actual output:

Promise!

@lofcz
Copy link
Contributor

lofcz commented Feb 18, 2024

Can confirm the behavior is still the same as of 3.0

@tom-b-iodigital
Copy link
Contributor

tom-b-iodigital commented Feb 21, 2024

You can use c# tasks, they are converted to promises and awaited correctly.

so looking at the first example here, this would work:

using Jint;
using System;
using System.Threading.Tasks;

var engine = new Engine();

engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.SetValue("setTimeout", new Func<int, Task>(setTimeout));


engine.Evaluate(@"

            setTimeout(10000)
                .then(res => {
                    log('resolved');
                })
                .catch(res => {
                    log('rejected');
                })
            ;
        ");

async Task setTimeout(int delay)
{
    await Task.Delay(delay).ConfigureAwait(false);
}

Just your standard C# and JS async/await way of working :)

I prefer to write it like this:

var engine = new Engine();

engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.SetValue("setTimeout", new Func<int, Task>(setTimeout));


engine.Evaluate(@"
        (async () => {
            await setTimeout(1000);
            log('resolved');
        })();
        ");

async Task setTimeout(int delay)
{
    await Task.Delay(delay).ConfigureAwait(false);
}

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

5 participants