我用下面的代码创建了一个简单的示例。目标是能够使用 Angular 的 $q
服务中的 deferred
Promise,但在回调中包含 $q
,该回调本身返回一个结果:是在主 Controller 中处理的。
我认识到错误显然是 $q
的 Promise 需要立即返回,以便它可以“等待”结果,并且将该 Promise 放在回调中会阻止它返回立即地。因此,下面的代码显然是一个不正确的策略。
我的问题是要问实现与上述愿望相当的效用的最佳实践是什么,包括回调和返回 promise 的需要。
function asyncGreet(name, cb) {
cb(name)
}
function okToGreet(name) {
return name.length > 10
}
var promise = asyncGreet('Robin Hood', function(name) {
var deferred = $q.defer();
setTimeout(function() {
deferred.notify('About to greet ' + name + '.');
if (okToGreet(name)) {
deferred.resolve('Hello, ' + name + '!');
} else {
deferred.reject('Greeting ' + name + ' is not allowed.');
}
}, 1000);
return deferred.promise;
});
promise.then(function(greeting) {
console.log('Success: ' + greeting);
}, function(reason) {
console.log('Failed: ' + reason);
});
最佳答案
为了整合评论并解决其他答案对异步 API 的有些令人困惑的描述,我决定提供一个答案:
如果我们假设有一些异步非 promise /基于回调的API,例如asyncGreet
,它可以像这样被 mock :
function asyncGreet(name, cb){
// simulate async
setTimeout(function(){
someCondition ? cb({message: "Hello, " + name + "!"}) :
cb({error: "Greeting " + name + " is not allowed."});
}, 2000);
}
(就本示例而言,asyncGreet
是第三方 API 不在我们的控制范围内)
将其转换为 $q
基于 promise 的 API,您将使用 $q
(使用 $q.defer
或使用 $q
构造函数 - 事实上,我刚刚注意到 Angular's documentation shows the $q
-constructor approach )。
例如,您可以创建一个 greeterSvc
服务:
app.factory("greeterSvc", function greeterSvcFactory($q){
return {
greet: function(name){
return $q(function(resolve, reject){
asyncGreet(name, function cb(data){
if ('error' in data) {
reject(data.error); // extract reason
} else {
resolve(data.message); // extract greeting message
}
});
});
}
}
})
greeterSvc.greet
的消费者API 则可以.then
例如,记录一些内容 - 就像您所做的那样(尽管我会使用 .catch
代替)
greeterSvc.greet("Robin Hood")
.then(function(greeting) {
console.log('Success: ' + greeting);
})
.catch(function(reason) {
console.log('Failed: ' + reason);
});
关于javascript - 在回调中使用 $q - 这可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31257078/