如何处理链式承诺

时间:2017-05-26 13:47:12

标签: angularjs promise angularfire

我有点困惑,我应该如何处理我的情况中的承诺。

这是我的工厂:

return {
  getCategory: function(categoryId) {
    var ref = firebase.database().ref().child('categories').child(categoryId);
    var category = $firebaseObject(ref);
    return category.$loaded().then(function() {
        return category;
    });
  },
  getEntry: function(categoryId, entryId) {
    var ref = firebase.database().ref().child('entries').child(categoryId).child(entryId);
    var entry = $firebaseObject(ref);
    return entry.$loaded().then(function() {
        return entry;
    });
  }
}

在我的工厂,我尽量避免这样做:

var d = $q.defer();
if() {
    d.resolve();
}
return d.promise;

因为$ loaded()返回一个promise本身。

这是我的控制者:

var categoryId = 'abc';
var entryId = 'def';
// so here i'm getting the category
MyFactory.getCategory(categoryId)
.then(function(category) {
    if(category.$value === null)
    {
        $scope.error = 'The category does not exist';
    }
    else if(new Date() > new Date(category.expireDate))
    {
        $scope.error = 'The category has expired';
    }
    else {
        $scope.category = category;
        // if no errors
        return MyFactory.getEntry(category.$id, entryId);
    }
})
.then(function(entry) {
    if(entry.$value === null)
    {
        $scope.error = 'No such entry';
    }
    else {
        $scope.entry = entry;
    }
})
.catch(function(error) {
    console.error(error);
});

我想要实现的是首先获取类别,然后是否存在某些错误,分别获取条目。数据来自Firebase数据库。

这有点起作用,但是当我想要做下一个时,我不确定如何处理这个承诺。然后不要将它们嵌套在另一个中:

MyFactory.getCategory().then(function(category) {
    if(no category errors) {
        MyFactory.getEntry().then(function() {
            // ...
        });
    }
});

现在我在控制台中遇到错误(类型错误条目未定义),例如类别已过期或不存在。 当我回来的时候,我觉得我在控制器上做错了但是我不太确定,希望你能帮我消除所有的疑惑。

所以真正的问题是我应该如何处理正确,按预期工作? 感谢。

1 个答案:

答案 0 :(得分:1)

如果出现错误,您应该返回被拒绝的承诺。

请看以下示例:

MyFactory
    .getCategory(categoryId)
    .then(function (category) {
        if (category.$value === null) {
            return $q.reject('The category does not exist');
        }
        if (new Date() > new Date(category.expireDate)) {
            return $q.reject('The category has expired');
        }
        $scope.category = category;
        return MyFactory.getEntry(category.$id, entryId);
    })
    .then(function (entry) {
        if (entry.$value === null) {
            return $q.reject('No such entry');
        }
        $scope.entry = entry;
    })
    .catch(function (error) {
        $scope.error = error;
    });

不要忘记将$q注入您的控制器。

修改

我还建议您将“错误逻辑”移至您的服务,因此控制器将始终收到.then(data => { ... })中的数据或.catch(error => { ... })中的错误字符串。这将使您的控制器更清晰,如果您在不同的控制器中使用这些服务方法,您也不必在那里复制您的逻辑。

<强>服务

return {
    getCategory: function(categoryId) {
        var ref = firebase.database().ref().child('categories').child(categoryId);
        var category = $firebaseObject(ref);
        return category.$loaded().then(function() {
            if (category.$value === null) {
                return $q.reject('The category does not exist');
            }
            if (new Date() > new Date(category.expireDate)) {
                return $q.reject('The category has expired');
            }
            return category;
        });
    },
    getEntry: function(categoryId, entryId) {
        var ref = firebase.database().ref().child('entries').child(categoryId).child(entryId);
        var entry = $firebaseObject(ref);
        return entry.$loaded().then(function() {
            if (entry.$value === null) {
                return $q.reject('No such entry');
            }
            return entry;
        });
    }
}

<强>控制器

MyFactory
    .getCategory(categoryId)
    .then(function (category) {
        $scope.category = category;
        return MyFactory.getEntry(category.$id, entryId);
    })
    .then(function (entry) {
        $scope.entry = entry;
    })
    .catch(function (error) {
        $scope.error = error;
    });