从父函数读取变量

时间:2014-12-28 01:04:35

标签: javascript jquery variables global-variables nedb

这是来自我的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函数之后调用变量时,都返回&#34; undefined&#34;。

如果我使用

  

var variablename =

  

VARIABLENAME =

执行因以下错误而停止:&#34; ReferenceError:未定义titulo&#34; (在我尝试从交换机调用它的地方)。

在所有这三种情况下,librodb.find函数中的警报都会返回被返回的值。

我如何定义或调用变量?

2 个答案:

答案 0 :(得分:3)

您遇到的是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.titulowindow.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肯定需要一些时间来适应。

P.S。你真的不应该把价值放在窗口上。我还没有在你的示例代码中修复它,但是现在它在同一个函数中你应该能够摆脱全局变量并简单地使它们成为正常变量。

答案 1 :(得分:1)

您只需要重新组织代码,以便在回调中使用回调的依赖关系。例如:

&#13;
&#13;
for (var i = 0; i < docs.length; i++) {
  librodb.find({
    _id: docs[i].libro
  }, function(err, bookdoc) {
    var titulo = bookdoc[0].titulo;
    var 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 ("' + titulo + '", ISBN: ' + ISBN + ') producidos.</li>');
        break;
      case 2:
        libreriadb.find({
          _id: docs[i].libreria
        }, function(err, librarydoc) {
          var 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 ("' + titulo + '", ISBN: ' + ISBN + ') devueltos por Libreria ("' + 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 ("' + titulo + '", ISBN: ' + ISBN + ') en stock ingresaron por "' + docs[i].descripcion + '".</li>');
        break;
    }

  });

}
&#13;
&#13;
&#13;

总体而言,您的回调函数将执行所有依赖于其结果的处理。

根据经验,你不应该混淆窗口对象,所以你几乎不想在那里定义任何变量,当然不是像这样的简单情况。