Node.js 异步同步

Posted

技术标签:

【中文标题】Node.js 异步同步【英文标题】:Node.js async to sync 【发布时间】:2013-05-11 07:11:12 【问题描述】:

我怎样才能做到这一点

var asyncToSync = syncFunc();

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

我试图从异步一中获取同步功能, 我需要它来使用 FreeTds 异步查询作为同步查询

【问题讨论】:

异步回调始终在函数堆栈清除后运行。因此,不可能同步返回 ansyc 结果。任何启动异步操作的同步函数都必须在异步操作开始之前返回。 相反,您想让外部函数异步,方法是让它接受一个在query的回调内部调用的回调。 查询函数是否执行数据库调用?如果是这样,DB 客户端可能会提供该查询功能的同步版本。 重复:How to block on asynchronous functions in javascript(但没有多少好的解释性答案) 【参考方案1】:

如今,这种生成器模式在许多情况下都可以成为出色的解决方案:

// 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

【讨论】:

这在主函数之外仍然是异步的,如果你把console.log("EOF")放在最后一行,你会立即看到do you want this? EOF。这实际上是一个手工制作的async/await 实现【参考方案2】:

使用deasync - 一个用 C++ 编写的模块,它将 Node.js 事件循环暴露给 JavaScript。该模块还公开了一个sleep 函数,该函数会阻塞后续代码,但不会阻塞整个线程,也不会导致忙等待。您可以将sleep 函数放入您的while 循环中:

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;

【讨论】:

这是唯一一个你不必在 Fiber 中运行的(如果你不控制调用代码,你就不能总是这样做) 确实!这是唯一一个适用于我的案例。谢谢!【参考方案3】:

您遇到的问题是您的紧的 while 循环被阻塞了。所以我认为您的查询回调永远不会运行。我认为您需要使用 setTimeout 等来防止函数阻塞,但如果您这样做,函数将在调用回调之前返回。此功能必须在较低级别实现。

如果您在浏览器中,您可以查看this article。在节点中,您必须依赖于您查询的任何内容的实现。它可能提供也可能不提供同步方法。

【讨论】:

【参考方案4】:

我一直在使用syncrhonize.js 并取得了巨大的成功。甚至还有一个挂起的拉取请求(效果很好)来支持具有多个参数的异步函数。比 node-sync imho 更好也更容易使用。额外的好处是它具有易于理解和详尽的文档,而 node-sync 没有。

【讨论】:

【参考方案5】:

你可以用node-sync lib做到这一点

var sync = require('sync');

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

注意:您的查询必须使用标准回调调用(首先出现错误):回调(错误,结果)。 如果您无法更改查询方法,只需创建 .async() 包装器(参见 github 链接)。

【讨论】:

我有带有回调错误和结果的异步函数,“sync(function())”是否能够在正常的 js 同步函数中返回值? 没有。 sync() 只是新的线程上下文。它不返回任何东西。只需用它包装所有代码,您就可以在异步函数上使用 .sync。

以上是关于Node.js 异步同步的主要内容,如果未能解决你的问题,请参考以下文章

node.js学习读写文件(同步异步)

Node.js - 我啥时候应该做异步的事情,啥时候做同步

node.js同步及异步读取写入删除文件1

关于Node.js异步转同步

同步和异步编程有啥区别(在node.js中)

Node.js 同步循环或迭代异步语句