I've read a dozen blog posts and StackOverflow answers but my factory won't return its results to the controller. In the controller, I first make an object to send data to the factory, then call the factory:
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
})
The data comes back undefined. Here's my factory:
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
The return from the factory happens before the data comes back from the database. I don't understand how to make the factory wait for the promise to resolve before doing the return to the controller.
Also, I don't understand what toController: toController is. I know that either the key or the value is the function that the controller calls, but why is the function both the key and the value? Can I refactor the function to get rid of
return {
toController: toController
};
I had
returnin the wrong place. Here's my working code for the factory:The only change was moving the
returnfrom inside thecase(and inside theforEachloop) to outside theforEachloop. Apparently the old (broken) code failed toreturnthe result out of the promise function, so thetoControllerfunction didn't have access to the result.Rephrasing the issue, there are four nested functions:
toControlleris a function..then) is a function.forEachloop is a function.The factory needs two
returns, in the 2nd and 3rd functions. No return is needed in the 4th function becausevideoWordsArrayis on the same scope, i.e., is accessible from the 3rd nested function. The 3rd nested loop has toreturnto the 2nd nested loop, which returns to the controller.