不能 return 从异步 AngularJS 工厂到控制器的结果
Can't return results from async AngularJS factory to controller
我已经阅读了很多博客文章和 Whosebug 答案,但我的工厂不会 return 将其结果发送给控制器。在controller中,我先做一个对象给工厂发送数据,然后调用工厂:
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
};
首先我看到你使用应用工厂的方式不对/这和应用服务是一样的
在工厂中,你必须创建你的承诺,然后 return 到控制器,你将使用两个函数处理它;第一个是成功函数,第二个是错误
试试这段代码,你会更好地理解它
我从不使用 firebase 但我认为其他数据库也是如此
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();
});
我把 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 个函数不需要 return,因为 videoWordsArray
在同一范围内,即可以从第 3 个嵌套函数访问。第三个嵌套循环必须 return
到第二个嵌套循环,return 到控制器。
我已经阅读了很多博客文章和 Whosebug 答案,但我的工厂不会 return 将其结果发送给控制器。在controller中,我先做一个对象给工厂发送数据,然后调用工厂:
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
};
首先我看到你使用应用工厂的方式不对/这和应用服务是一样的
在工厂中,你必须创建你的承诺,然后 return 到控制器,你将使用两个函数处理它;第一个是成功函数,第二个是错误
试试这段代码,你会更好地理解它
我从不使用 firebase 但我认为其他数据库也是如此
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();
});
我把 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 个函数不需要 return,因为 videoWordsArray
在同一范围内,即可以从第 3 个嵌套函数访问。第三个嵌套循环必须 return
到第二个嵌套循环,return 到控制器。