32

How can I make this work

var asyncToSync = syncFunc();

function syncFunc() {
    var sync = true;
    var data = null;
    query(params, function(result){
        data = result;
        sync = false;
    });
    while(sync) {}
    return data;
}

I tried to get sync function from async one, I need it to use FreeTds async query as sync one

3
  • 5
    Async callbacks always run after the function stack has cleared. Therefore, it is not possible to synchronously return an ansyc result. Any synchronous function that initiated an async action must necessarily have returned before the async action started. Instead, you want to make your outer function also asynchronous by having it accept a callback that is called inside the callback to query. Commented May 16, 2013 at 13:33
  • 1
    Does the query function perform a database call? If so, the DB client may provide synchronous version of that query function. Commented May 16, 2013 at 13:43
  • Duplicate: How to block on asynchronous functions in JavaScript (but not many good explanatory answers) Commented May 16, 2013 at 13:45

5 Answers 5

27

Use deasync - a module written in C++ which exposes Node.js event loop to JavaScript. The module also exposes a sleep function that blocks subsequent code but doesn't block entire thread, nor incur busy wait. You can put the sleep function in your while loop:

var asyncToSync = syncFunc();

function syncFunc() {
    var sync = true;
    var data = null;
    query(params, function(result){
        data = result;
        sync = false;
    });
    while(sync) {require('deasync').sleep(100);}
    return data;
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is the only one that you don't have to run inside a Fiber (which you can't always do if you don't control the calling code)
Indeed! This is the only one worked with my case. Thanks!
13

Nowadays this generator pattern can be a fantastic solution in many situations:

// nodejs script doing sequential prompts using async readline.question function

var main = (function* () {

  // just import and initialize 'readline' in nodejs
  var r = require('readline')
  var rl = r.createInterface({input: process.stdin, output: process.stdout })

  // magic here, the callback is the iterator.next
  var answerA = yield rl.question('do you want this? ', res=>main.next(res))    

  // and again, in a sync fashion
  var answerB = yield rl.question('are you sure? ', res=>main.next(res))        

  // readline boilerplate
  rl.close()

  console.log(answerA, answerB)

})()    // <-- executed: iterator created from generator
main.next()     // kick off the iterator, 
                // runs until the first 'yield', including rightmost code
                // and waits until another main.next() happens

1 Comment

this still async outside main function, if you put console.log("EOF") at last line, you will see do you want this? EOF immediately. this is actually a hand-made async/await implementation
9

You can do it with node-sync lib

var sync = require('sync');

sync(function(){
  var result = query.sync(query, params);
  // result can be used immediately
})

Notice: your query must use standart callback call (with error first): callback(error, result). If you can't change query method, just create .async() wrapper (see github link).

2 Comments

I have async function with callback err and resutls, is "sync(function(){})" able to return value in normal js sync function ?
No. sync() is just new thread context. It not retun anything. Just wrap all code by it and you could use .sync on async functions.
3

I've been using syncrhonize.js with great success. There's even a pending pull request (which works quite well) to support async functions which have multiple parameters. Far better and easier to use than node-sync imho. Added bonus that it has easy-to-understand and thorough documentation, whereas node-sync does not.

2 Comments

the link yields "Site not found" error
and? I left that reply over three years ago. the project has probably moved or been abandoned.
2

The issue you are having is that your tight while loop is blocking. So I don't think your query callback will ever be run. I think you need to use setTimeout or the like to prevent the function from blocking, but should you do so, the function will return before the callback is called. This functionality must be implemented at a lower level.

If you are in the browser, you might check out this article. In node you have to rely on the implementation of whatever you're querying. It may or may not provide synchronous methods.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.