Во всех этих сценариях outerScopeVar
изменяется или назначается значение асинхронно или происходит в более позднее время (ожидание или прослушивание какого-либо события), для которого текущее выполнение не будет ждать. Таким образом, все эти случаи текущего потока выполнения приводит к outerScopeVar = undefined
Давайте обсудим каждый пример (я обозначил часть, которая называется асинхронно или задерживается для возникновения некоторых событий):
1.
Здесь мы регистрируем eventlistner, который будет выполнен на этом конкретном событии. Загрузите изображение. Затем текущее выполнение будет продолжено со следующими строками img.src = 'lolcat.png';
и alert(outerScopeVar);
, между тем событие может не произойти. т. е. funtion img.onload
ожидают, что упомянутое изображение будет загружаться, как можно скорее. Это будет происходить во всем следующем примере: событие может отличаться.
2.
Здесь событие тайм-аута играет роль , который вызывается обработчиком по истечении указанного времени. Здесь 0
, но все же он регистрирует асинхронное событие, которое будет добавлено в последнюю позицию Event Queue
для выполнения, что делает гарантированную задержку.
3.
На этот раз ajax обратный вызов.
4.
Узел можно рассматривать как король асинхронного кодирования. Если отмеченная функция зарегистрирована как обработчик обратного вызова, которая будет выполнена после чтения указанного файла.
5.
Очевидное обещание (что-то будет сделано в будущем) является асинхронным. см. . Каковы различия между отложенными, обещаниями и будущими в JavaScript?
https://www.quora.com/Whats-the-difference-between-a -promise-и-обратный вызов-в-Javascript
У вашего фрагмента кода неприятный побочный эффект:
var userId;
tableOne.on('value', function (snapshot) {
userId = snapshot.val().userId; // line 1 (results like 1,2,3,4,5,6)
anotherTable.child('userdetails').child(userId).once('value', function(mediaSnap) {
console.log(userId + ":" + mediaSnap.val().name);
});
});
Вы не объявляете userId
как переменную, а это значит, что она становится глобальной переменной в JavaScript. И поскольку функция обратного вызова выполняется асинхронно, есть хорошая вероятность, что глобальные значения будут изменены к моменту, когда вам это нужно.
Решение состоит в том, чтобы сделать userId
локальной переменной функции обратного вызова :
tableOne.on('value', function (snapshot) {
var userId = snapshot.val().userId; // line 1 (results like 1,2,3,4,5,6)
anotherTable.child('userdetails').child(userId).once('value', function(mediaSnap) {
console.log(userId + ":" + mediaSnap.val().name);
});
});
Это обеспечит захват каждого значения userId
внутри функции.
Решение для соединения списка:
tableOne.orderByKey().on("value", function (snapshot) {
//console.log(snapshot.val());
snapshot.forEach(function (data) {
tableTwo.once('value').then(function (info) {
info = info.val();
});
});
});