我已经阅读了十几篇博文和StackOverflow答案,但我的工厂不会将其结果返回给控制器。在控制器中,我首先创建一个对象将数据发送到工厂,然后调用工厂:
let videoWordsArrayObject = { // make object to send data to factory
clipInMovie: $scope.clipInMovie,
movieTitle: $scope.movieTitle,
userUID: $scope.user.uid,
videoWords: $scope.videoWords
};
videoWordsArrayFactory.toController(videoWordsArrayObject) // call factory
.then(function(data) {
console.log(data); // undefined
})
data
返回undefined
。这是我的工厂:
app.factory('videoWordsArrayFactory', function($q) {
function toController(videoWordsArrayObject) {
let videoWordsArray = [];
// get the data from the controller
var clipInMovie = videoWordsArrayObject.clipInMovie;
var userUID = videoWordsArrayObject.userUID;
var videoWords = videoWordsArrayObject.videoWords;
var movieTitle = videoWordsArrayObject.movieTitle;
var qPromise = $q.when(firebase.database().ref('users').orderByChild('uid').equalTo(userUID).once('value')) // query Firebase Database by the user's UID to find the user's account
.then(function(snapshot) { // get a snapshot of the user's data
snapshot.forEach(function(childSnapshot) { // iterate through the user's data
switch (true) {
// cases that don't return data to the controller
case childSnapshot.val()[movieTitle][movieTitle + "_" + clipInMovie][0].word === videoWords[0]: // array of completed words in Firebase with correct first element
videoWordsArray = childSnapshot.val()[movieTitle][movieTitle + "_" + clipInMovie];
console.log(videoWordsArray); // data is here
return videoWordsArray;
break;
default:
console.log("Error");
} // close switch-case
}); // close snapshot forEach loop
}) // close snapshot promise
.catch(function(error) {
console.error('Error ', error);
}); // close snapshot catch
return qPromise; // no data here
}; // close toController
return {
toController: toController
};
}); // close factory
工厂的return
发生在数据从数据库返回之前。在对控制器执行return
之前,我不明白如何让工厂等待承诺解决。
另外,我不明白toController: toController
是什么。我知道键或值是控制器调用的函数,但为什么函数既是键又是值?我可以重构函数来摆脱
return {
toController: toController
};
答案 0 :(得分:0)
首先我看到你以错误的方式使用应用工厂/应用服务是同样的事情
在工厂,你必须创建你的承诺并返回控制器后,你将用两个功能处理它;第一个是成功函数,第二个是错误
尝试此代码,您将更好地理解
我从不使用firebase,但我认为考虑到其他dbs是一样的
app.factory('videoWordsArrayFactory', function($q) {
return {
toController: toController
}
function toController(videoWordsArrayObject) {
return $q.when(firebase.database().ref('users').orderByChild('uid').equalTo(videoWordsArrayObject.userUID).once('value')) //this return a promise
}
});
// in your controller
app.controller("myController",function("$scope, videoWordsArrayFactory"){
var videoWordsArrayObject = { // make object to send data to factory
clipInMovie: $scope.clipInMovie,
movieTitle: $scope.movieTitle,
userUID: $scope.user.uid,
videoWords: $scope.videoWords
};
$scope.callPromise = function(){
videoWordsArrayFactory.toController(videoWordsArrayObject).then(function(snapshot){
//handle here youre logic after promise is resolved
console.log(snapshot);
},function(error){
console.log(error);
})
}
$scope.callPromise();
});
答案 1 :(得分:0)
我在错误的地方return
。这是我工厂的工作代码:
app.factory('asyncVideoWordsArrayFactory', function($q) {
return {
toController: toController
};
function toController(asyncVideoWordsArrayObject) {
var videoWordsArray = [];
var clipInMovie = asyncVideoWordsArrayObject.clipInMovie;
var movieTitle = asyncVideoWordsArrayObject.movieTitle;
var userUID = asyncVideoWordsArrayObject.userUID;
var videoWords = asyncVideoWordsArrayObject.videoWords;
var qPromise = $q.when(firebase.database().ref('users').orderByChild('uid').equalTo(userUID).once('value'))
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var userData = childSnapshot.val();
switch (true) {
// cases for catching error conditions
case userData[movieTitle][movieTitle + "_" + clipInMovie][0].word === videoWords[0]:
videoWordsArray = userData[movieTitle][movieTitle + "_" + clipInMovie];
break;
default:
console.log("Error");
} // close switch-case
}); // close forEach loop
return videoWordsArray; // return result to toController
}) // close snapshot promise
.catch(function(error) {
console.log('Error: ' + error);
});
return qPromise; // return result to controller
} // close toController
}); // close factory
唯一的变化是将return
从case
内部(以及forEach
循环内部)移动到forEach
循环之外。显然,旧的(损坏的)代码未能将return
结果从promise函数中删除,因此toController
函数无法访问结果。
重新解决这个问题,有四个嵌套函数:
toController
是一个功能。.then
)是一个函数。forEach
循环是一个函数。工厂需要两个returns
,在第二和第三个功能中。第4个函数不需要返回,因为videoWordsArray
在同一范围内,即可从第3个嵌套函数访问。第三个嵌套循环必须return
到第二个嵌套循环,返回控制器。