这是来 self 的 node-webkit 应用程序的 javascript 代码,使用 jquery 和 nedb 来管理数据库。
librodb.find({_id: docs[i].libro}, function (err, bookdoc) {
window.titulo = bookdoc[0].titulo;
window.ISBN = bookdoc[0].ISBN;
});
从数据库中读取条目并将它们返回到数组 (bookdoc) 中。
for (var i = 0; i < docs.length; i++) {
librodb.find({_id: docs[i].libro}, function (err, bookdoc) {
window.titulo = bookdoc[0].titulo;
window.ISBN = bookdoc[0].ISBN;
});
switch(docs[i].razon){
case 1:
$(".listed").append('<li><i class="fa fa-institution"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') producidos.</li>');
break;
case 2:
libreriadb.find({_id: docs[i].libreria}, function (err, librarydoc) {
window.nombre = librarydoc[0].nombre;
});
$(".listed").append('<li><i class="fa fa-institution"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') devueltos por Libreria ("'+window.nombre+'"), recibo '+docs[i].documento+'.</li>');
break;
case 3:
$(".listed").append('<li><i class="fa fa-question"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') en stock ingresaron por "'+docs[i].descripcion+'".</li>');
break;
}
}
问题是变量 window.titulo 和 window.ISBN 是在读取数据库函数内部定义的,但在外部没有定义。
如果我用
window.variablename=
当我在 de librodb.find 函数之后调用变量时,两者都返回“undefined”。
如果我用
var variablename=
或
variablename=
执行停止并出现以下错误:“ReferenceError: titulo is not defined”(在我尝试从开关调用它的地方)。
在所有这三种情况下,librodb.find 函数内的警报都会返回应该返回的值。
我必须如何定义或调用变量?
最佳答案
您遇到的是 javascript 中异步编程的众多陷阱之一。
以下代码的含义有细微差别:
librodb.find({_id: docs[i].libro}, function (err, bookdoc) {
window.titulo = bookdoc[0].titulo;
window.ISBN = bookdoc[0].ISBN;
});
librodb.find
方法是异步的,这意味着它有需要做的后台工作(可能需要等待磁盘访问或网络流量)。它不会停止所有其他代码的运行,而是开始在后台执行操作,一旦完成,它将使用结果调用您的代码。
因此,您看到的是,当您的代码尝试使用 titulo 和 ISBN 运行时,回调尚未被调用,这是您的代码设置 window.titulo
和 window. ISBN
尚未运行!
相反,您需要延迟运行代码,直到查找结果返回。为此,请将其移入回调函数。当然这意味着一个简单的 for 循环不会做你想做的事。相反,您可以使用回调编写自己的异步循环,或使用诸如 async.js 之类的库。 .
如果你自己写它可能看起来像下面这样:
var i = 0;
function processNext() {
librodb.find({_id: docs[i].libro}, function (err, bookdoc) {
window.titulo = bookdoc[0].titulo;
window.ISBN = bookdoc[0].ISBN;
switch(docs[i].razon){
case 1:
$(".listed").append('<li><i class="fa fa-institution"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') producidos.</li>');
next();
break;
case 2:
libreriadb.find({_id: docs[i].libreria}, function (err, librarydoc) {
window.nombre = librarydoc[0].nombre;
$(".listed").append('<li><i class="fa fa-institution"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') devueltos por Libreria ("'+window.nombre+'"), recibo '+docs[i].documento+'.</li>');
next();
});
break;
case 3:
$(".listed").append('<li><i class="fa fa-question"></i><i class="fa fa-sign-in"></i>El '+docs[i].fecha+' '+docs[i].cantidad+' Libros ("'+window.titulo+'", ISBN: '+window.ISBN+') en stock ingresaron por "'+docs[i].descripcion+'".</li>');
next();
break;
}
});
function next() {
i++;
if(i < docs.length) {
processNext();
}
else {
// DONE
}
}
processNext(); // Start the loop
回调和异步 javascript 肯定需要一些时间来适应。
附注您真的不应该将值放在窗口上。我没有在你的示例代码中修复它,但现在它在同一个函数中,你应该能够摆脱全局变量并简单地使它们成为普通变量。
关于javascript - 从父函数读取变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27672901/