如何在angularjs中传递回调函数给once().then()

How to pass a callback function to once().then() in angularjs?

本文关键字:函数 once 回调 then angularjs      更新时间:2023-09-26

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

我的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异步检索数据?谢谢。

您可以利用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;
}]);

这将类似于任何$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)来处理任何被拒绝的承诺

我认为你实际上没有调用回调,使用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;
}]);