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
Trigger an Event with Prototype
Create an Instance of a Class in Es6 with a Dynamic Name
What Is the Dollar Sign in JavaScript, If Not Jquery
Using Async/Await Inside a React Functional Component
Internal/Modules/Cjs/Loader.Js:582 Throw Err
How to Find a Number in a String Using JavaScript
Using a Variable in Mongodb Update
JavaScript - Difference Between Array and Array-Like Object
What Is Browser.Ignoresynchronization in Protractor
Mobile Safari: JavaScript Focus() Method on Inputfield Only Works with Click
How to Perform an Http File Upload Using Express on Cloud Functions for Firebase (Multer, Busboy)
What Is Settimeout Doing When Set to 0 Milliseconds
Jquery - Script Tags in the HTML Are Parsed Out by Jquery and Not Executed
How to Remove Element from an Array in JavaScript
Angular 2: Import External Js File into Component
Referencing Another Schema in Mongoose
How to Check Whether an Object Is a Date
Componentdidmount Equivalent on a React Function/Hooks Component