2014-12-28 4 views
1

Это код javascript моего приложения node-webkit, работающий с jquery и nedb для управления базами данных.Чтение переменных из родительской функции

librodb.find({_id: docs[i].libro}, function (err, bookdoc) { 
window.titulo = bookdoc[0].titulo; 
window.ISBN = bookdoc[0].ISBN; 
}); 

Это считывает записи из db и возвращает их в массив (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=

Когда я называю переменные после того, как де librodb.find функции как возврат «неопределенном».

, если я использую

var variablename=

или

variablename=

Выполнение останавливается со следующей ошибкой: «ReferenceError: título не определен» (в том месте, где я пытаюсь вызвать его из переключатель).

Во всех трех случаях предупреждение внутри функции librodb.find возвращает возвращаемое значение.

Как мне определить или вызвать переменные?

ответ

3

Что вы используете, это одна из многих ошибок асинхронного программирования в javascript.

Значение кода наблюдения является нюансами:

Метод librodb.find является асинхронным, то есть он имеет фоновую работу он должен делать (возможно, он должен ждать доступа к диску, или сетевого трафика). Вместо того, чтобы останавливать запуск всего другого кода, он начинает делать что-то в фоновом режиме, и как только это будет закончено, он вызовет ваш код с результатами.

Итак, что вы видите, так это то, что когда ваш код пытается использовать titulo и ISBN работает, callback еще не был вызван, это ваш код window.titulo и window.ISBN еще не запущен!

Вместо этого вам нужно отложить запуск кода до тех пор, пока результаты поиска не вернутся. Для этого переместите его внутри функции обратного вызова. Конечно, это означает, что простой цикл не будет делать то, что вы хотите. Вместо этого вы можете либо написать свой собственный асинхронный цикл, используя обратные вызовы, либо использовать библиотеку, такую ​​как 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 

Callbacks и Asynchronous JavaScript определенно займет некоторое время, чтобы привыкнуть.

p.s. Вы действительно не должны помещать значения в окно. Я не исправил это в вашем примере кода, но теперь, когда он находится внутри одной и той же функции, вы сможете избавиться от глобальных переменных и просто сделать их нормальными переменными.

+0

Я пробовал это раньше (без следующей функции), он не работал (я не помню, почему: B, я попробую его снова), но зачем нужна следующая функция? doesnt цикл for делает это автоматически? без этого цикл повторяется до того, как чтение db закончилось? –

+0

@JiancerounoTaringa Цикл 'for' выполняет в основном одно и то же, но делает это синхронно; теперь есть способ приостановить цикл, ожидая результатов операций поиска. Поскольку нам пришлось переместить оператор switch внутри обратного вызова, если мы использовали цикл for, он увеличивал бы весь путь до doc.length до того, как оператор switch фактически выполнит. Поэтому 'i' будет равно' doc.length', что совсем не то, что вы хотите. Также результаты поиска могут выйти из строя, и ваши вставленные элементы могут оказаться в неправильном порядке. – Hargobind

+0

О, я только что запомнил, внутри librodb.find работает bookdoc, но документы (из родительской функции поиска) не работают, а внутри libreriadb.find работает librarydoc, но оба документа и bookdoc не делают –

1

Вам просто нужно реорганизовать свой код, чтобы в обратном вызове использовались зависимости от обратного вызова. Например:

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; 
 
    } 
 

 
    }); 
 

 
}

Большая картина является то, что ваша функция будет делать всю обработку, которая зависит от его результата.

Как правило, вы не должны загромождать объект окна, поэтому вы почти никогда не хотите определять какие-либо переменные там, конечно, не для простого случая, подобного этому.