如何将回调函数传递给angularjs中的once()。then()?

时间:2016-10-23 13:12:33

标签: javascript angularjs firebase callback firebase-realtime-database

我有一个单独的模型和一个教师名单的控制器。

我的teacherModel.js是:

app.factory('Teacher', [function() {
   function Teacher(teacher) {
     // constructor
   };
   Teacher.prototype = {
        setTeacher: function(teacher) {
            angular.extend(this, teacher);
        },
        getAllTeachers: function(callback) {
            var scope = this;
            var ref = firebase.database().ref('/xxx/teachers');
            ref.once('value').then(function(snapshot) {
                teachersList = snapshot.val();
                scope.setTeacher(teachersList);
                // THERE'S A PROBLEM HERE...
                // I'm trying to pass this callback from the controller:
                callback;
            });
        }
    };  
    return Teacher;
}]);

现在,从我的控制器,我使用回调函数调用getAllTeachers()方法:

app.controller('teacherMainCtrl', ['$scope', 'Teacher', function($scope, Teacher){
    var teacher = new Teacher()
    teacher.getAllTeachers(function() {
       $scope.teachers = teacher;
       console.log($scope.teachers);
    });
}]);

问题是console.log($scope.teachers);没有将任何内容记录到控制台。我根本不认为回调正在执行。

有人可以帮我弄清楚我做错了什么或建议在从firebase异步检索数据后,从控制器向模型数据添加功能的更好方法吗?感谢。

2 个答案:

答案 0 :(得分:2)

您可以利用once返回firebase承诺的事实,以便您可以将代码更改为以下内容:

app.factory('Teacher', [function() {
   function Teacher(teacher) {
     // constructor
   };
   Teacher.prototype = {
        setTeacher: function(teacher) {
            angular.extend(this, teacher);
        },
        getAllTeachers: function() {
            var scope = this;
            var ref = firebase.database().ref('/xxx/teachers');
            return ref.once('value').then(function(snapshot) {      
                return snapshot.val();
            });
        }
    };  
    return Teacher;
}]);

这与其返回promise的任何$http请求的行为类似。现在,在您的控制器中,您可以像这样调用getAllTeachers()

app.controller('teacherMainCtrl', ['$scope', 'Teacher', function($scope, Teacher){
    var teacher = new Teacher()
    teacher.getAllTeachers().then(function (snapshotValues) {
        // What you returned in the promise above is populated in snapshotValues here
        $scope.teachers = snapshotValues;
    });
}]);

<强>更新

如果您想为特定方案使用$q服务,可以执行以下操作:

app.factory('Teacher', ['$q', function($q) {
   function Teacher(teacher) {
     // constructor
   };
   Teacher.prototype = {
        setTeacher: function(teacher) {
            angular.extend(this, teacher);
        },
        getAllTeachers: function() {
            var defer = $q.defer();
            var scope = this;
            var ref = firebase.database().ref('/xxx/teachers');
            ref.once('value').then(function(snapshot) {      
                var val = snapshot.val();
                // Transform your data any way you want. 
                // Whatever you pass into resolve() will be available as a parameter in the subsequent then()

                defer.resolve(val);
            });

            return defer.promise;
        }
    };  
    return Teacher;
}]);

使用该方法仍然是一样的。您只需致电then()

即可
teacher.getAllTeachers()
    .then(function (whatYouPassedInResolve) {

});

另外需要注意的是,在工厂内的getAllTeachers方法中,我没有处理任何错误情况。这可以通过拒绝defer.reject(objectToSendBack)的承诺来实现。当您认为呼叫失败时,您可以传入您想要访问的任何数据。

只需将第二个参数的函数传递给`then(successCallback,errorCallback)来处理任何被拒绝的承诺。

答案 1 :(得分:1)

我认为您实际上并未调用回调,请使用callback()

app.factory('Teacher', [function() {
   function Teacher(teacher) {
     // constructor
   };
   Teacher.prototype = {
        setTeacher: function(teacher) {
            angular.extend(this, teacher);
        },
        getAllTeachers: function(callback) {
            var scope = this;
            var ref = firebase.database().ref('/xxx/teachers');
            ref.once('value').then(function(snapshot) {
                teachersList = snapshot.val();
                scope.setTeacher(teachersList);
                // THERE'S A PROBLEM HERE...
                // Try this
                callback();
            });
        }
    };  
    return Teacher;
}]);