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

providing another way for synchronise code to interface with asynchronise code #30634

Closed
TrevTheDev opened this issue Nov 25, 2019 · 11 comments
Closed
Labels
question Issues that look for answers.

Comments

@TrevTheDev
Copy link

Node's async await features are awesome, however, they do not provide a way to interface with calls that were not designed to work with async-await in mind. For example, proxies enable one to trap get requests, however, there is no way to do synchronise calls and then supply the result of those synchronise calls to the get request, unless the caller implements await.

One possible solution is the deasync library:

  get: () => {
    let result;
    (async ()=>{  
        result = await doSyncCalls(target);
     })();
     deasync.loopWhile(() => !result);
     return result;
  }

However, deasync has a bug where nested promises fail to resolve.

This feature is required whenever one is unable to alter the caller's code to work with await. So any third-party libraries that calls ones code, but which are not designed to be synchronise. Without this feature, there is no good way to respond to those libraries.

Node already recognises this problem by providing sync versions of some of its api calls, e.g. execSync, spawnSync etc. Node provides this functionality to its users, but they are unable to do similar to their users.

Without this feature, there is a whole set of situation that node will be unable to respond to.

@devsnek
Copy link
Member

devsnek commented Nov 25, 2019

Node's sync variants are separate C++ calls, they aren't just deasync'd versions of the async APIs.

At a very general level though, it's not possible to arbitrarily turn async apis into sync apis. I'd also say that anything relying on deasync is not something I would feel comfortable depending on.

@yorkie
Copy link
Contributor

yorkie commented Nov 25, 2019

For your example, I just figure out an easier way than deasync:

new Proxy(..., {
  get: function() {
    return child_process.execSync('your actual async works', 'utf8');
  }
});

It's working in sync and no any extra syntax is required, but it seems weird a bit just like what you have written in your example at Node.js, which the best practice is not going to block others. Another solution is to return promise at traps, and document this in package README:

const foobar = await mDelegatedObj.foobar;
// or
mDelegatedObj.foobar.then(() => ...);

@yorkie
Copy link
Contributor

yorkie commented Nov 25, 2019

And it's better to transfer the discussion to our nodejs/help repo, because this seems not related in Node.js core too much :)

@TrevTheDev
Copy link
Author

TrevTheDev commented Nov 25, 2019

@yorkie, yes your better example is what needs replication, except for for a broader set of functions than child_process.execSync. This would enable others to write code that mimics execSync in their code and write their own sync functions.

@TrevTheDev
Copy link
Author

TrevTheDev commented Nov 25, 2019

At a very general level though, it's not possible to arbitrarily turn async apis into sync apis.

Yes and that is why this feature is required, it could be something like

 const x = pause-await doSyncCalls(somVar)

That unlike await doesn't return a promise, but rather pauses execution in a non blocking way until the await is completed. Enabling an easy transition from sync to async.

@yorkie
Copy link
Contributor

yorkie commented Nov 25, 2019

This would enable others to write code that mimics execSync in their code and write their own sync functions.

Node.js should be focusing on event-based IO which means async, maybe another v8-based runtime for that purpose?

@devsnek
Copy link
Member

devsnek commented Nov 25, 2019

if you're asking for new language features, you should head over to https://tc39.es. Node.js can't add new language features.

@TrevTheDev
Copy link
Author

@devsnek, yes it could be a language feature, it could also be a feature node provides, or it could be a library such as deasync. Possibly the simplest solution is to enhance Node to enable deasync to actually work - from their github issue, it seems the Node team rejected their change.

Without this feature going from sync to async is fine, but going from async to sync is undoable. That would be fine if people never needed to do so, but even Node provides sync functions demonstrating the use-case.

@devsnek
Copy link
Member

devsnek commented Nov 26, 2019

I should've been a bit clearer. It's not possible to take an arbitrary function that performs some unknown async behaviour and make it synchronous. deasync exploits the fact that the majority of async behaviour in node applications is very similar: one-shot calls to libuv apis. However, as with the bug you linked, not everything follows that pattern.

Node is able to provide sync apis because it has specialized C++ code for those individual synchronous apis. We don't have an internal magic "syncify" api that could be exposed.

@addaleax
Copy link
Member

Also, just to be clear on one point: What deasync does is not officially supported by Node.js in any way. I would recommend against using it whenever possible.

@devsnek
Copy link
Member

devsnek commented Dec 10, 2019

I don't think there's anything actionable here, I'm going to close this out.

@devsnek devsnek closed this as completed Dec 10, 2019
@devsnek devsnek added the question Issues that look for answers. label Dec 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Issues that look for answers.
Projects
None yet
Development

No branches or pull requests

4 participants