
Security News
MCP Steering Committee Launches Official MCP Registry in Preview
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
node-force-sync
Advanced tools
Forces an async function to run synchronously using a separate node process
WARNING: This package should only be used in the exceptionally rare situation that converting to async code is not an option. Please don't use it as an excuse not to learn how Promises and
async
functions work.
node-force-sync
allows you to force synchronous execution of an async
function. This is not the same thing as the await
keyword, which is really just async execution made to look like sync execution. This package actually runs your async
functions synchronously.
Node.js itself provides no mechanism for forcing async code to block. Thus, the solution is hacky and has significant limitations:
console.log
calls will not be visibleconst { forceSync } = require('node-force-sync');
const myAsyncFunc = async (...args) => { /* ... */ };
const mySyncFunc = forceSync(myAsyncFunc);
mySyncFunc(1, 2, 3);
$ npm install node-force-sync
or
$ yarn add node-force-sync
function forceSync<A extends any[], R extends any>(asyncFunc: (...args: A) => Promise<R>, config?: Partial<ForceSyncConfig>): (...args: A) => R;
Accepts an async
function (and optional config) and returns a synchronous version of that function. Due to implementation details, your function is subject to several limitations:
Promise
. If it's an async function
, this requirement is already met.require()
from within the function itself.es2017
will generate an __awaiter
function out of scope. See Transpilation Workarounds for more details on how to deal with this.function forceSync<A extends any[], R extends any>(funcStr: string, config?: Partial<ForceSyncConfig>): (...args: A) => R;
Identical to forceSync(asyncFunc, config?), except you pass a function string instead of a function. There are benefits and drawbacks to using this overload:
In general, you should really only need this overload if you're trying to get around the issues caused by transpilation.
Both overloads of forceSync
allow an optional config argument.
type ForceSyncConfig = {
tagOpenWrappers?: [string, string],
tagCloseWrappers?: [string, string],
tmpFilePath?: string,
nodeExecutable?: string,
debug?: boolean,
};
const forceConfigDefaults: ForceSyncConfig = {
tagOpenWrappers: ['!!!', '!!!'],
tagCloseWrappers: ['!!!/', '!!!'],
tmpFilePath: '.',
nodeExecutable: 'node',
debug: false,
};
tagOpenWrappers
/ tagCloseWrappers
- In order to distinguish your function output/errors from other console output, the output/errors have to be wrapped in tags, for example: !!!OUTPUT!!!"your function output"!!!/OUTPUT!!!
. These tags have a beginning, middle, and end sections. In this example, the OUTPUT
is the "middle", and !!!
and /!!!
are the "wrappers." If your function happens to be outputting text that would get confused with these tags, you can change the defaults. For example, you might wish the tags to look like this instead: <OUTPUT></OUTPUT>
.tmpFilePath
- Your async code is written to a temporary JS file during execution. This is the path where you'd like these temporary files to be created.nodeExecutable
- Node.js must be invoked from the commandline as part of executing your async code.debug
- Logs extra information when your code is run, such as
const { forceSync } = require('node-force-sync');
const asyncGet = async (url: string) => {
const axios = require('axios');
return (await axios.get(url)).data;
};
const syncGet = forceSync(asyncGet);
const response = syncGet('https://postman-echo.com/get?foo=bar');
If you use TypeScript, Babel, or some other transpilation tool, chances are your function will fail to execute properly when forced to run synchronously. The primary reason for this is code being generated out of scope of your function, which conflicts with one of the package's major limitations. There are a few ways to work around this issue:
As long as your transpiler doesn't generate out-of-scope code, your function should run just fine. In the case of TypeScript, you need to target es2017
or later to avoid the generation of __awaiter
and __generator
. This is the best option if your runtime requirements allow it.
forceSync
forceSync
can also accept a function string rather than a function. The string you pass is not transpiled, so you can avoid the transpilation problem all together this way. This is a decent option if your code is relatively simple and you don't want to mess with transpilation settings.
Promise
instead of using async function
In the case of TypeScript, __awaiter
and __generator
are only generated when async function
is used. If you make your function manually return a Promise
instead, TS won't generate the out-of-scope code. This is a good option if you can't target es2017
or later and you're unwilling to lose type-safety/intellisense by encoding your function as a string.
Node.js itself cannot resolve a Promise synchronously. However, it can run a child process synchronously via execSync()
. A Node.js process will also not exit until any pending Promises are resolved. So putting these two pieces together, you can "force synchronous execution" by running the async code in a child Node.js process, which won't exit until the Promise has resolved and the parent Node.js process can synchronously wait for.
If you want more details, you'll have to look at the source!
FAQs
Forces an async function to run synchronously using a separate node process
The npm package node-force-sync receives a total of 45 weekly downloads. As such, node-force-sync popularity was classified as not popular.
We found that node-force-sync demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
Product
Socket’s new Pull Request Stories give security teams clear visibility into dependency risks and outcomes across scanned pull requests.
Research
/Security News
npm author Qix’s account was compromised, with malicious versions of popular packages like chalk-template, color-convert, and strip-ansi published.