Angular / Firebase Web App - 处理异步调用的最佳实践是什么

时间:2016-11-18 11:42:05

标签: javascript angularjs firebase firebase-realtime-database

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

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

func getFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
      let request = NSFetchRequest<NSFetchRequestResult>(entityName: "EntitySet")
      request.predicate = ...
      let eventSort = NSSortDescriptor(key: "event_name", ascending: true)
      let timeSort = NSSortDescriptor(key: "assigned_time", ascending: false)
      request.sortDescriptors = [eventSort, timeSort]
      return request
}

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

//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;
}])

所以这是我的问题:

  1. 我的第一个电话(getEventList)阻塞了吗?这就意味着console.info('[Ctrl] After getEventList()');在getEventList()完成之前不要执行?
  2. 如何调用loadEventList()阻塞,以便在事件列表完全加载并传递给控制器​​之前,我的控制器不再执行任何代码
  3. 满足这些需求的最佳做法是什么
  4. 谢谢!

1 个答案:

答案 0 :(得分:0)

  

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中用于处理异步操作的最佳实践。