javascript - 在回调中使用 $q - 这可能吗?

标签 javascript angularjs promise angular-promise

我用下面的代码创建了一个简单的示例。目标是能够使用 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/

相关文章:

Javascript正则表达式所有字符直到单词

javascript - 多个 Google 标记不会使用拖动监听器更新位置

javascript - 如何在 Sencha Touch 中向模型添加自定义验证规则

angularjs - 可以使用$$ prevSibling在 'transcluded'指令中访问作用域数据吗?

angularjs - <input> 模板的 ng-grid 问题

c++ - std::promise 的任何情况都不能被运行顺序生产然后消费的单个线程替换吗?

javascript - 在没有商店的情况下使用带有选择器列插件的 Dojo dgrid 吗?

javascript - 如何在 $http GET 方法中设置参数以从下拉 Angularjs 发送数据

javascript - 在 promise 中中止 ajax 请求

angular - 在@angular 的源代码中,为什么 NgForm 在它的函数中使用一个已经解析的 promise?