代码之家  ›  专栏  ›  技术社区  ›  Thomas David Kehoe

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

  •  -1
  • Thomas David Kehoe  · 技术社区  · 8 年前

    我已经读了十几篇博客文章和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 在数据从数据库返回之前发生。我不明白如何让工厂等到承诺解决后再做 回来 至控制器。

    还有,我不明白是什么 toController: toController 是我知道键或值是控制器调用的函数,但为什么函数同时是键和值呢?我可以重构函数以除去

    return {
      toController: toController
    };
    
    2 回复  |  直到 8 年前
        1
  •  0
  •   FarukT    8 年前

    首先,我发现你用错了应用程序工厂/它是应用程序服务的同一件事

    在工厂,您必须创建承诺并返回控制器,之后您将使用两个功能处理它;第一个是成功函数,第二个是错误函数

    尝试此代码,您会更好地理解它

    我从未使用过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();
    });
    
        2
  •  0
  •   Thomas David Kehoe    8 年前

    我有 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
    

    唯一的变化是移动 回来 从内部 case (和内部 forEach 回路)至外部 forEach公司 环显然,旧(坏)代码未能 回来 promise函数的结果 toController 函数无权访问结果。

    换言之,有四个嵌套函数:

    1. 工厂是一种功能。
    2. To控制器 是一个函数。
    3. 第二个承诺( .then )是一个函数。
    4. 这个 forEach公司 循环是一个函数。

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