【问题标题】:Angular/Firebase Web App - What's the best practice to handle asynchronous callsAngular/Firebase Web App - 处理异步调用的最佳实践是什么
【发布时间】:2016-11-18 11:42:05
【问题描述】:

让我们想象一个使用 Angular 和 Firebase 开发的网络应用。 在这个应用程序中,有一个页面,其中包含公共事件列表(从 Firebase 检索)显示为开关元素列表。 用户可以通过切换开关来注册/取消注册每个事件,它会自动更新他自己注册的事件列表(更新用户 Firebase db 的每个开关上的 ng-change)。

所以我创建了一个数据库服务:

//private
var eventList = [];
// methods
this.getEventList = function(){
    if(eventList.length > 0){
        console.info('[getEventList] Event list already fetched');
        return eventList;
    }
    else{
        console.info('[getEventList] Event list has never been fetched');
        this.loadEventList();
    }
}
this.loadEventList = function(){
    console.info('[LoadEventList] Fetch event list');
    var events = [];
    firebase.database().ref('events/').once('value').then(function(snap) {
        snap.forEach(function(item) {
            events.push({
                id: item.val().id,
                name: item.val().name,
                registered: false
            });
        });
        console.info('[LoadEventList] End of fetching');
        console.dir(events);
        eventList = events;
        return eventList;
    });
}

还有一个用户服务,我在其中编写了一个函数,该函数允许将用户注册到的事件列表与公共事件的全局列表同步。我想显示公共事件的完整列表以及根据用户所做的注册来切换的开关:

this.syncEventListWithUserEventss = function(listToSync){
    userRef.child('events/').once('value', function(snap){
        var userEvents = snap.val();

        // sync only if user registered at least one event
        if(userEvents) {
            for(var i = 0; i < userEvents.length; i++){
                for(var j = 0; j < listToSync.length; j++){
                    if(listToSync[j].id ==userEvents[i]){
                        listToSync[j].registered = true;
                    }
                }
            }
        }
    });
}

到目前为止,我的代码运行良好。但它在页面控制器中变得很棘手:

function ($scope, $stateParams, DatabaseService, UserService) {
    $scope.events = [];
    console.info('[Ctrl] Before getEventList()');
    console.dir($scope.events);

    $scope.events = DatabaseService.getEventList();
    console.info('[Ctrl] After getEventList()');
    console.dir($scope.events);

    UserService.syncEventListWitEventports($scope.events);

    $scope.updateUserEventList = UserService.updateUserEventList;
}])

结果:

[Ctrl] Before getEventList()
Array[0]

[getEventList] Event list has never been fetched
[LoadEventList] Fetch event list

[Ctrl] After getEventList()
undefined

[LoadEventList] End of fetching
Array[4]

所以这是我的问题:

  1. 我的第一个呼叫 (getEventList) 是否阻塞?这意味着 console.info('[Ctrl] After getEventList()');直到 getEventList() 完成才被执行?
  2. 如何使我的 loadEventList() 调用阻塞,以便我的控制器在事件列表完全加载并传递给控制器​​之前不会执行任何进一步的代码
  3. 满足这些需求的最佳做法是什么

谢谢!

【问题讨论】:

  • 使用回调或返回 Promise
  • 这不是我通过调用 loadEventList 所做的,其中 return 语句嵌套在 promise 中吗?在我的情况下有什么具体的解决方案吗?谢谢
  • 你在 loadEventList 中使用了一个 promise,但是那个函数没有返回任何东西,最好在那里传递一个回调。
  • 回调方法 - this.getEventList = function(cb){ / this.loadEventList(cb); / this.loadEventList = function(cb){ / return eventList; to cb(eventList); / DatabaseService.getEventList(function(data) {$scope.events = data; });
  • 确实效果更好!非常感谢!

标签: javascript angularjs firebase firebase-realtime-database


【解决方案1】:

return 语句嵌套在 promise 中?在我的情况下有什么具体的解决方案吗?

当作为.then 方法的参数提供的成功处理程序具有return 语句时,可以将派生的promise 返回给父函数。

this.loadEventList = function(){
    console.info('[LoadEventList] Fetch event list');
    var events = [];

    //retain promise
    var promise = firebase.database().ref('events/').once('value');
    //retain derived promise
    var derivedPromise = promise.then(function(snap) {
        snap.forEach(function(item) {
            events.push({
                id: item.val().id,
                name: item.val().name,
                registered: false
            });
        });
        console.info('[LoadEventList] End of fetching');
        console.dir(events);
        eventList = events;
        //return to chain data
        return eventList;
    });
    //return to parent function
    return derivedPromise;
};

返回的promise可以用来保存一个函数供以后处理

this.loadEventList().then(function successHandler(eventList) {
    //Put further processing here
    console.log(eventList);
});

提供给.then 方法的函数由$q 服务持有,直到异步操作解决。这是 AngularJS 中公认的处理异步操作的最佳实践。

【讨论】:

    猜你喜欢
    • 2018-02-14
    • 1970-01-01
    • 2019-01-04
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多