Call An Asynchronous Javascript Function Synchronously

前端 未结 8 1490
南方客
南方客 2020-11-22 17:37

First, this is a very specific case of doing it the wrong way on-purpose to retrofit an asynchronous call into a very synchronous codebase that is many thousands of lines lo

8条回答
  •  长情又很酷
    2020-11-22 17:59

    You can force asynchronous JavaScript in NodeJS to be synchronous with sync-rpc.

    It will definitely freeze your UI though, so I'm still a naysayer when it comes to whether what it's possible to take the shortcut you need to take. It's not possible to suspend the One And Only Thread in JavaScript, even if NodeJS lets you block it sometimes. No callbacks, events, anything asynchronous at all will be able to process until your promise resolves. So unless you the reader have an unavoidable situation like the OP (or, in my case, are writing a glorified shell script with no callbacks, events, etc.), DO NOT DO THIS!

    But here's how you can do this:

    ./calling-file.js

    var createClient = require('sync-rpc');
    var mySynchronousCall = createClient(require.resolve('./my-asynchronous-call'), 'init data');
    
    var param1 = 'test data'
    var data = mySynchronousCall(param1);
    console.log(data); // prints: received "test data" after "init data"
    

    ./my-asynchronous-call.js

    function init(initData) {
      return function(param1) {
        // Return a promise here and the resulting rpc client will be synchronous
        return Promise.resolve('received "' + param1 + '" after "' + initData + '"');
      };
    }
    module.exports = init;
    

    LIMITATIONS:

    These are both a consequence of how sync-rpc is implemented, which is by abusing require('child_process').spawnSync:

    1. This will not work in the browser.
    2. The arguments to your function must be serializable. Your arguments will pass in and out of JSON.stringify, so functions and non-enumerable properties like prototype chains will be lost.

提交回复
热议问题