【问题标题】:Convert an asynchronous function to a synchronous function将异步函数转换为同步函数
【发布时间】:2013-08-28 13:42:51
【问题描述】:

我使用某个 Node.js 类进行文本分类。最简单的形式是这样的:

function TextCategorizer(preprocessors) {
      ...
}

“预处理器”是一个函数数组,形式如下:

function(text) {
    return "<modified text>"
}

它们可用于例如删除标点符号、转换为小写等。

我可以像这样使用 TextCategorizer:

var cat = newTextCategorizer(preprocessors);
cat.train(text1,class1);
cat.train(text2,class2);
...
console.log(cat.classify(text3,class3);

按每个训练文本和分类文本的顺序调用预处理器。

现在,我需要添加一个新的预处理器功能 - 一个拼写纠正器。我发现最好的拼写更正了异步工作(通过网络服务),所以,函数看起来像这样:

correctSpelling(text, callback) {
     ... 
     callback(corrected_version_of_text);
}

即它不返回值,而是使用该值调用回调函数。

我的问题是:作为我发送给 TextCategorizer 的预处理器数组中的预处理器之一,我如何使用正确的拼写函数?

【问题讨论】:

  • 为什么不异步使用呢?异步是节点的口头禅。
  • 作为一个独立的函数,我当然可以异步使用。但正如我在问题中解释的那样,我想将它用作另一个模块的输入,该模块需要一个同步函数。
  • 通过异步调用将你的预处理器放在一个闭包中。然后在这个闭包中定义你的回调,这样回调函数就可以访问预处理器数组。
  • @ChrisCM “通过异步调用将你的预处理器放在一个闭包中”——这是什么意思?我该怎么做?
  • @ErelSegalHalevi 我相信 ChrisCM 的意思是我在下面的答案中发布的内容。

标签: node.js asynchronous


【解决方案1】:

如果你想把一堆任务按一定的顺序排列,你可以使用async 框架(npm install async)。有一个用于同步异步函数的特定功能,称为“系列”。

听起来您在使用同步和异步功能时遇到了问题。在这种情况下,我认为您应该将所有同步函数包装在一个异步函数中,就像这样

function asyncFunc(args, callback){
    process.nextTick(function() {
        callback(syncFunc(args));
    });
}

那么您应该使用async 模块将它们链接在一起。

看起来这可能会使异步函数同步。

waitfor on github

【讨论】:

  • "series" 接受一个异步函数数组,按顺序调用它们,并将结果返回给另一个回调。但是,我仍然不知道如何使用它将异步函数发送到需要同步函数的类...
  • @ErelSegalHalevi 你能包含更多代码吗?我不明白为什么你可以将同步回调异步传递给你的函数。
  • 您对 TextCategorizer 有什么访问权限?如果您可以获取源代码,我相信您可以检测基于事件的解决方案(我将根据您的回答进行描述。)
  • @JoshC,我认为您的回答与所需要的完全相反。如果我错了,请纠正我,但我认为问题不在于如何使同步函数显示为异步,而是在给定现有同步函数的管道的情况下,如何添加异步函数以便它可以同步运行。
  • @JoshC,虽然他可能拥有管道中的步骤,但管道的调用是不透明的。正如我在下面指出的那样,唯一的其他选择似乎是在 TextCategorizer 看到它们之前预处理文档,这意味着提供他自己的预处理管道。
【解决方案2】:

如果我上面关于我对您的问题的理解的评论是正确的,我不相信有一种方法可以按照您想要的方式取消异步调用,而无需修改您指出的 TextCategorizer 的源不会是最优的。

我唯一的另一个想法是在调用 train() 和分类之前通过现有的预处理器列表运行您的文档,这将允许您遵循 JoshC 的建议。

【讨论】:

    【解决方案3】:

    如果你真的想做,可以试试Fibers

    var Future = require('fibers/future'), wait = Future.wait;
    var fs = require('fs');
    
    // This wraps existing functions assuming the last argument of the passed
    // function is a callback. The new functions created immediately return a
    // future and the future will resolve when the callback is called (which
    // happens behind the scenes).
    var readdir = Future.wrap(fs.readdir);
    var stat = Future.wrap(fs.stat);
    
    Fiber(function() {
        // Get a list of files in the directory
        var fileNames = readdir('.').wait();
        console.log('Found '+ fileNames.length+ ' files');
    
        // Stat each file
        var stats = [];
        for (var ii = 0; ii < fileNames.length; ++ii) {
            stats.push(stat(fileNames[ii]));
        }
        wait(stats);
    
        // Print file size
        for (var ii = 0; ii < fileNames.length; ++ii) {
            console.log(fileNames[ii]+ ': '+ stats[ii].get().size);
        }
    }).run();
    

    未来 (https://github.com/laverdet/node-fibers#futures)

    【讨论】:

      猜你喜欢
      • 2012-07-25
      • 2015-06-25
      • 1970-01-01
      • 2018-03-21
      • 2018-01-11
      • 1970-01-01
      • 2015-10-15
      • 2014-03-29
      相关资源
      最近更新 更多