【问题标题】:Serial execution with Q promises带有 Q 承诺的串行执行
【发布时间】:2015-06-12 14:34:12
【问题描述】:

我想我误解了 Q 承诺的工作原理。我希望在下一个承诺开始之前解决我的第一个承诺,但这并没有发生。这是我的代码:

var Q = require('q');

function doWork(taskName) {
  var deferred = Q.defer();
  console.log('starting', taskName);
  setTimeout(function() { 
    console.log('done with', taskName);
    deferred.resolve(); 
  });

  return deferred.promise;
}

doWork('task one')
  .then(doWork('task two'))
  .then(function() { console.log('all done'); });

这段代码产生:

$ node test.js 
  starting task one
  starting task two
  done with task one
  done with task two
  all done

我希望它能产生:

$ node test.js 
  starting task one
  done with task one
  starting task two
  done with task two
  all done

我做错了什么?

【问题讨论】:

    标签: javascript q


    【解决方案1】:

    这行得通:

    doWork('task one')
      .then(function() {
        return doWork('task two')
      })
      .then(function() {
        console.log('all done'); 
      });
    

    这是有道理的——直接在then() 中调用doWork 会立即触发超时,而不是让Q 有机会等到task one 完成。

    【讨论】:

      【解决方案2】:

      原因是 doWork 需要作为函数来引用。如果你想在 '.then' 中引用一个函数,那么你只需给出函数名,你不传递参数。当解析器看到 .then(doWork('taskTwo')) 时,它将在 .then 被评估之前运行 doWork('taskTwo') 。它试图绑定函数参数。

      在这种情况下,如果您在前一个任务的已解决承诺中返回下一个任务的参数,那么解析器将以正确的参数和正确的顺序调用 doWork。

      var Q = require('q');
      function doWork(taskNum) {
          var deferred = Q.defer();
          console.log('starting', taskNum);
          setTimeout(function() { 
            console.log('done with task', taskNum);
            deferred.resolve(++taskNum); 
          });
      
          return deferred.promise;
      }
      
      doWork(1)
      .then(doWork)
      .then(function(lastTaskNum) { console.log('all done'); });
      

      【讨论】:

        【解决方案3】:

        使用 qrequest

        的示例代码
        var Q       = require('q'),
            request = require('request'),
            api     = {};
        
        
        api.post = function (options) {
        
            var deferred = Q.defer();
        
            request.post(options, function (error, response, body) {
                    error ? deferred.reject(error) : deferred.resolve(body);
            });
        
            return deferred.promise;
        };
        
        api.get = function (options) {
            var deferred = Q.defer();
        
            request.post(options, function (error, response, body) {
                    error ? deferred.reject(error) : deferred.resolve(response);
            });
        
            return deferred.promise;
        }
        
        api
            .post({url: 'https://foo.com'})
            .then(function (body) {
                    console.log(body);
                    return api.get({url: 'http://myspace.hell'});
            }, function (error) {
                    //error handling logic
            })
            .then(function (response) {
                    console.log(response);
            }, function (error) {
                    //error handling logic
            })
            .done(); //when you are done
        

        在上面的代码中,您可以看到我定义了 2 个 API 方法:getpost

        我正在使用request 库。

        • 我的 post api 方法,使用 request.post() 返回的响应对象的 body 解析承诺
        • 我的 get api 方法,通过 request.get() 调用的 response 解析承诺

        您可以确切地看到如何使用 Promise 链接这 2 个 api 调用。

        在第一个然后我返回第二个promise,以便我可以链接promise。

        【讨论】:

          猜你喜欢
          • 2016-03-07
          • 2017-10-04
          • 1970-01-01
          • 1970-01-01
          • 2018-08-02
          • 2017-07-01
          • 1970-01-01
          • 2016-01-10
          • 2015-02-25
          相关资源
          最近更新 更多