Node.js 将异步函数转换为同步函数

Node.js 将异步函数转换为同步函数,node.js,asynchronous,Node.js,Asynchronous,我使用某个Node.js类进行文本分类。最简单的形式如下所示: function TextCategorizer(preprocessors) { ... } var cat = newTextCategorizer(preprocessors); cat.train(text1,class1); cat.train(text2,class2); ... console.log(cat.classify(text3,class3); correctSpelling(text, c

我使用某个Node.js类进行文本分类。最简单的形式如下所示:

function TextCategorizer(preprocessors) {
      ...
}
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);
}
预处理器是以下形式的函数数组:

function(text) {
    return "<modified text>"
}
对每个训练文本和分类文本依次调用预处理器

现在,我需要添加一个新的预处理器函数-拼写更正器。我发现的最佳拼写更正是通过web服务异步工作的,因此,函数如下所示:

function TextCategorizer(preprocessors) {
      ...
}
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);
}
i、 它不返回值,而是使用该值调用回调函数

我的问题是:作为发送给TextCategorizer的预处理器数组中的一个预处理器,如何使用correctSpelling函数?

如果您想按特定顺序放置一组任务,可以使用框架npm install async。有一个用于同步异步函数的特定功能,称为series

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

function asyncFunc(args, callback){
    process.nextTick(function() {
        callback(syncFunc(args));
    });
}
然后,您应该使用异步模块将它们链接在一起

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

如果您想将一系列任务按一定顺序排列,可以使用框架npm安装异步。有一个用于同步异步函数的特定功能,称为series

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

function asyncFunc(args, callback){
    process.nextTick(function() {
        callback(syncFunc(args));
    });
}
然后,您应该使用异步模块将它们链接在一起

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


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


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

如果我上面关于我对您的问题的理解是正确的,我不相信有任何方法可以按照您想要的方式取消异步调用,如果不修改TextCategorizer的源代码,您指出这不是最佳的

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

如果您真的想这样做,您可以尝试一下

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();
参见FUTURES

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

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();


参见FUTURES

为什么不异步使用它?Async是节点咒语。作为一个独立的函数,我当然可以异步使用它。但正如我在问题中所解释的,我想将其用作另一个模块的输入,该模块需要一个同步函数。然后在此闭包中定义回调,以便回调函数可以访问预处理器数组。@ChrisCM将预处理器与异步调用一起放入闭包中-这是什么意思?我该怎么做?@erresegalhalevi我相信ChrisCM就是我在下面的答案中所说的意思。为什么不异步使用它呢?Async是节点咒语。作为一个独立的函数,我当然可以异步使用它。但正如我在问题中所解释的,我想将其用作另一个模块的输入,该模块需要一个同步函数。然后在此闭包中定义回调,以便回调函数可以访问预处理器数组。@ChrisCM将预处理器与异步调用一起放入闭包中-这是什么意思?我该怎么做?@erresegalhalevi我相信ChrisCM是指我在下面的答案中发布的内容。series接受异步函数数组,按顺序调用它们,并将结果返回给另一个回调。但是,我仍然不知道如何使用它将异步函数发送给需要同步函数的类…@ErelSegalHalevi您能再包含一点代码吗?我不明白为什么可以异步地将同步回调传递给函数。您对TextCategorizer有什么访问权限?如果你能找到源代码,我相信你可以提供一个基于事件的解决方案,我将根据你的回答来描述它。@JoshC,我认为你的回答与需要的正好相反。如果我错了,请纠正我,但我相信问题不在于如何使同步函数看起来是异步的,而在于给定一个现有同步函数的管道,如何添加一个异步函数以便它可以同步运行。@JoshC,虽然他可能拥有管道中的步骤,但管道的调用是不透明的。正如我在下面指出的,唯一的其他选择似乎是在TextCategoriz之前预处理文档
er可以看到它们,这意味着提供自己的预处理管道。series接受异步函数数组,按顺序调用它们,并将结果返回给另一个回调。但是,我仍然不知道如何使用它将异步函数发送给需要同步函数的类…@ErelSegalHalevi您能再包含一点代码吗?我不明白为什么可以异步地将同步回调传递给函数。您对TextCategorizer有什么访问权限?如果你能找到源代码,我相信你可以提供一个基于事件的解决方案,我将根据你的回答来描述它。@JoshC,我认为你的回答与需要的正好相反。如果我错了,请纠正我,但我相信问题不在于如何使同步函数看起来是异步的,而在于给定一个现有同步函数的管道,如何添加一个异步函数以便它可以同步运行。@JoshC,虽然他可能拥有管道中的步骤,但管道的调用是不透明的。正如我在下面指出的,唯一的其他选择似乎是在TextCategorizer看到文档之前对文档进行预处理,这意味着提供他自己的预处理管道。