我想问这个问题,因为我不确定我的 Node.js 逻辑是否正确
我有一组 id,需要使用 redis 的 get 方法查询。在检查了某个值之后(假设我正在检查我使用给定“键”获得的对象是否具有空名称),我将它们添加到列表中。这是我的示例代码;
var finalList = [];
var list = [];
redisClient.smembers("student_list", function(err,result){
list = result; //id's of students
console.log(result);
var possibleStudents = [];
for(var i = 0; i < list.length; i++){
redisClient.get(list[i], function(err, result){
if(err)
console.log("Error: "+err);
else{
tempObject = JSON.parse(result);
if(tempObject.name != null){
finalList.push(tempObject);
}
}
});
}
});
console.log("Goes here after checking every single object");
但正如预期的那样,由于 Node 的异步特性,它没有检查列表中的每个 id,而是执行“Goes here...”。我的需要是在检查每个 id 后应用其余过程(在 redis 数据库中映射并检查名称)。但我不知道该怎么做。也许如果我可以将回调附加到 for 循环并确保我的其余函数在循环完成后开始运行(我知道这是不可能的,但只是提供一个想法)?
最佳答案
我会按照您在问题中建议的路线进行操作,并将自定义回调附加到您的获取函数:
function getStudentsData(callback) {
var setList = [];
var dataList = [];
redisClient.smembers("student_setList", function(err,result) {
setList = result; //id's of students
for(var i = 0; i < setList.length; i++) {
redisClient.get(setList[i], function(err, result) {
if(err) {
console.log("Error: "+err);
} else {
tempObject = JSON.parse(result);
if(tempObject.name != null) {
dataList.push(tempObject);
}
}
});
}
if(dataList.length == setList.length) {
if(typeof callback == "function") {
callback(dataList);
}
console.log("getStudentsData: done");
} else {
console.log("getStudentsData: length mistmach");
}
});
}
getStudentsData(function(dataList) {
console.log("Goes here after checking every single object");
console.log(dataList.length);
//More code here
});
这可能是最有效的方法;或者,您可以依赖老派的 while 循环,直到数据准备就绪:
var finalList = [];
var list = [0];
redisClient.smembers("student_list", function(err,result) {
list = result; //id's of students
var possibleStudents = [];
for(var i = 0; i < list.length; i++) {
redisClient.get(list[i], function(err, result) {
if(err) {
console.log("Error: "+err);
} else {
tempObject = JSON.parse(result);
if(tempObject.name != null) {
finalList.push(tempObject);
}
}
});
}
});
process.nextTick(function() {
if(finalList.length == list.length) {
//Done
console.log("Goes here after checking every single object");
console.log(dataList.length);
//More code here
} else {
//Not done, keep looping
process.nextTick(arguments.callee);
}
});
我们使用 process.nextTick 而不是实际的 while 来确保其他请求不会同时被阻止;由于 Javascript 的单线程特性,这是首选方式。为了完整起见,我将其放入,但前一种方法更有效并且更适合 node.js,所以除非涉及重大重写,否则请继续使用。
这两种情况都依赖于异步回调,这毫无值(value),这意味着它之外的任何代码仍然有可能在其他代码完成之前运行。例如,使用我们的第一个片段:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
最后一个 console.log 几乎可以保证在传递给 getStudentsData 的回调被触发之前运行。解决方法?为其设计,这就是 node.js 的工作方式。在我们上面的例子中,这很简单,我们只需在传递给 getStudentsData 的回调中调用 console.log 仅,而不是在它之外。其他场景需要与传统过程编码有更多不同的解决方案,但一旦您了解它,您就会发现事件驱动和非阻塞实际上是一个非常强大的功能。
关于Node.js 和 Redis;等待循环结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12819610/
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
我是Ruby的新手,有些闭包逻辑让我感到困惑。考虑这段代码:array=[]foriin(1..5)array[5,5,5,5,5]这对我来说很有意义,因为i被绑定(bind)在循环之外,所以每次循环都会捕获相同的变量。使用每个block可以解决这个问题对我来说也很有意义:array=[](1..5).each{|i|array[1,2,3,4,5]...因为现在每次通过时都单独声明i。但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?array=[]foriin1..5j=iarray[5,5,5,5,5]因为j每次循环都是新的,我认为每次循环都会捕获不同的变量。例如,这绝对
基本上,我只是试图在满足特定条件时停止程序运行其余行。unlessraw_information.firstputs"Noresultswerereturnedforthatquery"breakend然而,在程序运行之前我得到了这个错误:Invalidbreakcompileerror(SyntaxError)执行此操作的正确方法是什么? 最佳答案 abort("Noresultswerereturnedforthatquery")unlesscondition或unlessconditionabort("Noresultswer
我正在开发一个Rails应用程序,我需要在其中找到给定特定偏移量或时区的夏令时开始和结束日期。我基本上在我的数据库中保存了从用户浏览器接收到的时区偏移量(“+3”,“-5”),我想在它出现时修改它由于夏令时的变化。我知道Time实例变量有dst?和isdst方法,如果存储在它们中的日期在夏令时与否。>Time.new.isdst=>true但是使用它来查找夏令时的开始和结束日期会占用太多资源,而且我还必须为我拥有的每个时区偏移量执行此操作。我想知道更好的方法。 最佳答案 好的,基于你所说的和@dhouty'sanswer:您希望能够
我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1
使用ruby的watir测试网络应用程序时,浏览器最后会保持打开状态。网上的一些建议是,要进行真正的单元测试,您应该在每次测试时(在拆卸调用中)打开和关闭浏览器,但这很慢而且毫无意义。或者他们做这样的事情:defself.suites=superdefs.afterClass#Closebrowserenddefs.run(*args)superafterClassendsend但这会导致摘要输出不再显示(诸如“100次测试、100次断言、0次失败、0次错误”之类的内容仍应显示)。我怎样才能让ruby或watir在我的测试结束时关闭浏览器? 最佳答案
rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http: