首页 文章

无法将异步AngularJS工厂的结果返回给控制器

提问于
浏览
-1

我已经阅读了十几篇博文和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
};

2 回答

  • 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();
    });
    
  • 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
    

    唯一的变化是将 returncase (并在 forEach 循环内)移动到 forEach 循环之外 . 显然,旧的(损坏的)代码未能通过promise函数返回结果,因此 toController 函数无法访问结果 .

    重新解决这个问题,有四个嵌套函数:

    • 工厂是一个功能 .

    • toController 是一个函数 .

    • 第二个承诺( .then )是一个函数 .

    • forEach 循环是一个函数 .

    工厂需要两个 returns ,在第二和第三功能 . 第4个函数不需要返回,因为 videoWordsArray 在同一范围内,即可从第3个嵌套函数访问 . 第三个嵌套循环必须 return 到第二个嵌套循环,它返回到控制器 .

相关问题