【问题标题】:How to use defer() the right way?如何正确使用 defer()?
【发布时间】:2015-07-01 13:17:24
【问题描述】:

如何正确使用 defer?我这里有两个函数,其中一个 defer 使用正确吗?它在哪一个中被错误地使用了?为什么分别。为什么不呢?

第一个例子:

getFoo1: function() {
  var dfd = $q.defer();

  db.allDocs({include_docs: true}, function(err, response) {
    if(err) {
      console.log(err);
      dfd.reject(err);
    } else {
      var qcs = [];
      for(var i=0; i < response.total_rows; i++) {
        if(response.rows[i].doc.type == 'bar') {

          var qc = {id: response.rows[i].doc._id,
            isFoo: true
          };

          oneFunction(qc)
          .then(anotherFunction(qc))
          .then(qcs.push(qc));
        }
      }
      dfd.resolve(qcs);
    }
  });
  return dfd.promise;
},

第二个例子:

getFoo2: function() {
  var dfd = $q.defer();

  db.allDocs({include_docs: true}, function(err, response) {
    if(err) {
      dfd.reject(err);
    } else {
      dfd.resolve(response);
    }
  });

  return dfd.promise
  .then(function(response) {
    var foo = [];
    for(var i=0; i < response.total_rows; i++) {
      if(response.rows[i].doc.type == 'bar') {
        var qc = {id: response.rows[i].doc._id,
          isFoo: true
        };

        return oneFunction(qc)
        .then(anotherFunction(qc))
        .then(foo.push(qc));
      }   
    }
  }, function(err){
     console.log(err);
  });
},

oneFunction 不会异步执行任何操作。

anotherFunction 异步执行某些操作(从外部数据库检索数据)。

编辑:感谢@Bergi,正确的函数应该如下所示:

getFoo3: function() {
  var dfd = $q.defer();

  db.allDocs({include_docs: true}, function(err, response) {
    if(err) {
      dfd.reject(err);
    } else {
      dfd.resolve(response);
    }
  });

  return dfd.promise
  .then(function(response) {
    var foos = [];

  for (var i=0; i < response.total_rows; i++) {
    if (response.rows[i].doc.type == 'bar') {
      var qc = {id: response.rows[i].doc._id,
        isFoo: true
      };
      var foo = oneFunction(qc);
      foos.push(foo);
    }
  }

  var promises = foos.map(anotherFunction); // make a promise for each foo
  return $q.all(promises);

  }, function(err){
     console.log(err);
  });
},

【问题讨论】:

  • then 你应该传递对函数的引用,但是你可以像anotherFunction(qc) 这样即时调用函数。所以似乎两者都使用不正确:-)
  • 能否详细说明您的评论?在哪个then 部分?相反,@Grundy 函数应该是什么样子?
  • 如果你解释你的期望,我可以试着解释它应该如何。无论如何,我的意思是 .then(anotherFunction(qc)) 应该像 .then(function(){anotherFunction(qc)}) 直到 anotherFunction 不返回函数
  • anotherFunction()如何得到它的参数qc,@Grundy?
  • 关闭需要 :-)

标签: javascript promise deferred


【解决方案1】:

您在第二个示例中正确使用了 $q.defer[1] - 为 db.allDocs 异步调用的响应创建了一个承诺(仅此而已)。正如@Benjamin 在 cmets 中提到的那样,尽管 pochdb 似乎已经返回了承诺,所以它是不必要的(但没有错)。

第一个例子只是一团糟,将 promise 的构造与错误日志和不祥的循环纠缠在一起。

1:除了dfd.promise(),它不是函数而是属性。去dfd.promise.then(…)


但是,该循环是一个非常不同的主题,并且在两个 sn-ps 中似乎都是错误的。几点:

  • 在第二个 sn-p 中,您的 return 来自循环主体中的回调函数,就在满足谓词的第一次迭代中。
  • 如果oneFunction(qc) 不是异步的,它不需要(阅读:不应该)返回一个promise - 或者如果它没有,那么.then(…) 调用是错误的。
  • anotherFunction(qc) 似乎返回了一个承诺(如你所说,它是异步的)。但是你不能把这个承诺传递给.then(),那里应该有一个回调函数!
  • foo.push(qc) 也是如此 - 它不是您将传递给 .then() 的回调函数。
  • 毕竟,您在那个循环中做一些异步操作。在这里,you have to usePromise.all 现在!

如果我必须打赌,我会说你需要

.then(function(response) {
  var foos = [];
  for (var i=0; i < response.total_rows; i++) {
    if (response.rows[i].doc.type == 'bar') {
      var qc = {id: response.rows[i].doc._id,
        isFoo: true
      };
      var foo = oneFunction(qc);
      foos.push(foo);
    }
  }
  var promises = foos.map(anotherFunction); // make a promise for each foo
  return $q.all(promises);
})

【讨论】:

  • response.rows 可以是 mapd,因为它是一个数组,除此之外看起来不错 :)
  • 是的,filtered 和 mapd,但我想保持接近原始代码。
  • @thadeuszlay:不,对于谓词response.rows[i].doc.type == 'bar',标准的Array filter 就足够了。
猜你喜欢
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 2011-07-12
  • 2017-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多