从 Firebase 的 DataSnapshot 列出数组的项目时,应用程序首次加载失败
App Fails First Load When Listing Array's Item from a DataSnapshot from Firebase
我正在将 DataSnapshot 存储到 $scope 数组中,因此 ng-repeat 到 HTML div 更新了我的 "result list"
问题是,当我 运行 代码,输入一个值并点击 运行 DataSnapshot 函数时,第一个结果没有出现在应用程序屏幕上,只出现在应用程序的登录浏览器的控制台。如果我再次 运行 该函数,结果就会出现。如果我更改输入并再次单击按钮(运行 函数),则此输入会在第一次尝试时出现。
那么,这就是您可能需要的东西:
从第一次尝试打印(数据出现在控制台上但不在应用程序上):
第二次尝试打印(数据在控制台上出现两次,在应用程序上出现一次):
第三次尝试使用另一个输入进行打印(数据在控制台上出现一次,在应用程序上出现一次):
代码:
index.html
<div class="list card">
<div class="item item-body" ng-repeat="locker in lockers">
<a href="#" class="item item-icon-right text-center">
<img ng-src="{{imageSrc}}" style="width: 35px; height: auto;">
<p style="text-align: center">
Locker - {{locker.number}}
<br>
{{key}}
</p>
<i class="icon ion-chevron-right"></i>
</a>
</div>
app.js
angular.module('starter', ['ionic', 'firebase'])
.controller('LockerCtrl', ["$scope", "$firebaseArray", function($scope,$firebaseArray, snapshot){
var lockersRef = new Firebase('https://ifrjarmariosdb.firebaseio.com/armarios');
$scope.getButtonClicked = function() {
var lockernumber = document.getElementById('lockerNumberInput').value;
if(lockernumber.length > 0){
lockerInputedNumber = parseInt(lockernumber);
lockersRef.on('value', function(snapshot){
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
});
}
正如您从照片中看到的那样,我在根据 Firebase 的数值更改图像源时也遇到了一些麻烦。如果你能帮我解决这个问题,那将是一个很大的帮助。
拜托,我不是在寻求此方法的解决方案,如果您知道其他方法,我也请您post。
谢谢!
此代码开始从 Firebase 加载数据:
lockersRef.on('value', function(snapshot){
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
加载是异步发生的。由于数据可用之前需要时间,因此浏览器继续执行 JavaScript after 这段代码。
当数据从服务器返回时,它会执行您的回调函数。但在那一点上,AngularJS 不再期望对 $scope
.
进行任何更改
解决方案是让 AngularJS 知道您已经更改了范围。最简单的方法是将回调包装到 $timeout()
调用中:
lockersRef.on('value', function(snapshot){
$timeout(function() {
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
});
有些人 运行 遇到了同样的问题:
关于您的代码我注意到的其他几点:
您正在下载所有储物柜,然后过滤用户在客户端输入的储物柜。这是在浪费您的用户可能要付费的带宽。更好的方法是使用 Query:
将过滤留给 Firebase
var query = lockersRef.orderByChild('number').equalTo(lockerInputedNumber);
query.on('value', function(snapshot){
AngularJS+Firebase 有一个名为 AngularFire 的绑定库,它会自动处理 $timeout()
事情。它建立在您现在使用的 Firebase JavaScript SDK 之上,因此它们可以完美地互操作。
我正在将 DataSnapshot 存储到 $scope 数组中,因此 ng-repeat 到 HTML div 更新了我的 "result list"
问题是,当我 运行 代码,输入一个值并点击 运行 DataSnapshot 函数时,第一个结果没有出现在应用程序屏幕上,只出现在应用程序的登录浏览器的控制台。如果我再次 运行 该函数,结果就会出现。如果我更改输入并再次单击按钮(运行 函数),则此输入会在第一次尝试时出现。
那么,这就是您可能需要的东西:
从第一次尝试打印(数据出现在控制台上但不在应用程序上):
代码:
index.html
<div class="list card">
<div class="item item-body" ng-repeat="locker in lockers">
<a href="#" class="item item-icon-right text-center">
<img ng-src="{{imageSrc}}" style="width: 35px; height: auto;">
<p style="text-align: center">
Locker - {{locker.number}}
<br>
{{key}}
</p>
<i class="icon ion-chevron-right"></i>
</a>
</div>
app.js
angular.module('starter', ['ionic', 'firebase'])
.controller('LockerCtrl', ["$scope", "$firebaseArray", function($scope,$firebaseArray, snapshot){
var lockersRef = new Firebase('https://ifrjarmariosdb.firebaseio.com/armarios');
$scope.getButtonClicked = function() {
var lockernumber = document.getElementById('lockerNumberInput').value;
if(lockernumber.length > 0){
lockerInputedNumber = parseInt(lockernumber);
lockersRef.on('value', function(snapshot){
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
});
}
正如您从照片中看到的那样,我在根据 Firebase 的数值更改图像源时也遇到了一些麻烦。如果你能帮我解决这个问题,那将是一个很大的帮助。
拜托,我不是在寻求此方法的解决方案,如果您知道其他方法,我也请您post。
谢谢!
此代码开始从 Firebase 加载数据:
lockersRef.on('value', function(snapshot){
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
加载是异步发生的。由于数据可用之前需要时间,因此浏览器继续执行 JavaScript after 这段代码。
当数据从服务器返回时,它会执行您的回调函数。但在那一点上,AngularJS 不再期望对 $scope
.
解决方案是让 AngularJS 知道您已经更改了范围。最简单的方法是将回调包装到 $timeout()
调用中:
lockersRef.on('value', function(snapshot){
$timeout(function() {
snapshot.forEach(function(data){
var number = data.val().number;
if(number == lockerInputedNumber){
$scope.key = data.key();
$scope.lockers = [data.val()];
console.log(data.val());
if(number == 101){ -
$scope.imageSrc = "img/locker_test2.png";
}
else{
$scope.imageSrc = "img/locker_test.jpg";
}
}
});
});
有些人 运行 遇到了同样的问题:
关于您的代码我注意到的其他几点:
您正在下载所有储物柜,然后过滤用户在客户端输入的储物柜。这是在浪费您的用户可能要付费的带宽。更好的方法是使用 Query:
将过滤留给 Firebasevar query = lockersRef.orderByChild('number').equalTo(lockerInputedNumber); query.on('value', function(snapshot){
AngularJS+Firebase 有一个名为 AngularFire 的绑定库,它会自动处理
$timeout()
事情。它建立在您现在使用的 Firebase JavaScript SDK 之上,因此它们可以完美地互操作。