How to Wrap Async Function Calls into a Sync Function in Node.Js or JavaScript

How to wrap async function calls into a sync function in Node.js or Javascript?

deasync turns async function into sync, implemented with a blocking mechanism by calling Node.js event loop at JavaScript layer. As a result, deasync only blocks subsequent code from running without blocking entire thread, nor incuring busy wait. With this module, here is the answer to the jsFiddle challenge:

function AnticipatedSyncFunction(){
var ret;
setTimeout(function(){
ret = "hello";
},3000);
while(ret === undefined) {
require('deasync').runLoopOnce();
}
return ret;
}

var output = AnticipatedSyncFunction();
//expected: output=hello (after waiting for 3 sec)
console.log("output="+output);
//actual: output=hello (after waiting for 3 sec)

(disclaimer: I am the co-author of deasync. The module was created after posting this question and found no workable proposal.)

Managing sync and async functions in an algorithm call stack

If you don't want to make the function async and propagate this up the chain, use .then(). You'll need to duplicate the following code inside .then(); you can simplify this by putting it in its own function.

function maybeRepeat() {
if (stop_condition) {
finish();
} else {
calcStep1();
}
}

function calcStep3() {
// do more calculations
pushToResults();

if (some_condition) {
getData().then(maybeRepeat);
} else {
maybeRepeat()
}
}

Does wrapping a node.js sync function make it perform the same as its async equivalent?

No.

The whole point of async is that the actual work, which is done by readFileSync(), happens off the event loop.

It is completely impossible to call a synchronous function and make it async.

Does putting synchronous functions in an async function still block nodejs?

If I put require in an async function and call that async function, does it block nodejs?

Yes, it does. If the module you are using require() to load is not already cached, then it will block the interpreter to load the module from disk using synchronous file I/O. The fact that it's in an async function doesn't affect anything in this regard.

async functions don't change blocking, synchronous operations in any way. They provide automatic exception handling and allow the use of await and always return a promise. They have no magic powers to affect synchronous operations within the function.

FYI, in nearly all cases, modules you will need in your code should be loaded at module initialization. They can then be referenced later from other code without blocking the interpreter to load them.

Wrap native (c++) method inside a Promise

I recently transformed gdal-next (https://github.com/yocontra/node-gdal-next) to a completely asynchronous API (https://github.com/mmomtchev/node-gdal-async).

I will probably end writing a tutorial because it is a common problem.

It is far from trivial, but basically it boils down to creating asynchronous workers (Napi::AsyncWorker) for each job and then invoking a JS callback on completion. It is this callback that will resolve the Promise - or once you have a function with a callback you can simply use util.promisify to return a Promise.

You can also check https://github.com/nodejs/node-addon- api/blob/main/doc/async_worker.md for barebones example:

#include <napi.h>

#include <chrono>
#include <thread>

using namespace Napi;

class EchoWorker : public AsyncWorker {
public:
EchoWorker(Function& callback, std::string& echo)
: AsyncWorker(callback), echo(echo) {}

~EchoWorker() {}
// This code will be executed on the worker thread
void Execute() override {
// Need to simulate cpu heavy task
std::this_thread::sleep_for(std::chrono::seconds(1));
}

void OnOK() override {
HandleScope scope(Env());
Callback().Call({Env().Null(), String::New(Env(), echo)});
}

private:
std::string echo;
};
#include <napi.h>

// Include EchoWorker class
// ..

using namespace Napi;

Value Echo(const CallbackInfo& info) {
// You need to validate the arguments here.
Function cb = info[1].As<Function>();
std::string in = info[0].As<String>();
EchoWorker* wk = new EchoWorker(cb, in);
wk->Queue();
return info.Env().Undefined();

Sync vs async for file write in NodeJS

Use fs.Promises API instead of a classic with a callback.

await fsPromises.writeFile(req.file.path + '.webp', data)


Related Topics



Leave a reply



Submit