如何处理链式承诺
How to handle chained promises
我有点困惑在我的情况下应该如何处理承诺。
这是我的工厂:
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() return本身就是一个承诺。
这是我的控制器:
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 数据库。
这是一种工作方式,但是我不确定当我想执行下一个 .then 时我应该如何处理 promise 并且 不要像这样将它们一个一个地嵌套在另一个中:
MyFactory.getCategory().then(function(category) {
if(no category errors) {
MyFactory.getEntry().then(function() {
// ...
});
}
});
现在我在控制台中收到一个错误(它是未定义的类型错误条目),例如类别已过期或不存在。
我想我 return 时我在控制器中做错了,但我不太确定,希望你能帮助我消除所有疑虑。
所以真正的问题是我应该如何正确处理这个问题才能按预期工作?
谢谢
当出现错误时,你应该return拒绝承诺。
看下面的例子:
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
注入您的控制器。
编辑
我还建议您将 "error logic" 移动到您的服务中,这样控制器将始终收到 .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;
});
我有点困惑在我的情况下应该如何处理承诺。
这是我的工厂:
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() return本身就是一个承诺。
这是我的控制器:
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 数据库。
这是一种工作方式,但是我不确定当我想执行下一个 .then 时我应该如何处理 promise 并且 不要像这样将它们一个一个地嵌套在另一个中:
MyFactory.getCategory().then(function(category) {
if(no category errors) {
MyFactory.getEntry().then(function() {
// ...
});
}
});
现在我在控制台中收到一个错误(它是未定义的类型错误条目),例如类别已过期或不存在。 我想我 return 时我在控制器中做错了,但我不太确定,希望你能帮助我消除所有疑虑。
所以真正的问题是我应该如何正确处理这个问题才能按预期工作? 谢谢
当出现错误时,你应该return拒绝承诺。
看下面的例子:
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
注入您的控制器。
编辑
我还建议您将 "error logic" 移动到您的服务中,这样控制器将始终收到 .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;
});