Q承诺的串行执行

时间:2013-03-11 23:29:03

标签: javascript q

我认为我误解了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

我做错了什么?

3 个答案:

答案 0 :(得分:7)

这有效:

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

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

答案 1 :(得分:4)

原因是doWork需要作为函数引用。如果要引用'.then'中的函数,那么只需给出函数名称,就不要传递参数。当解析器看到.then(doWork('taskTwo'))时,它将运行doWork('taskTwo'),然后甚至评估.then。它试图绑定函数参数。

在这种情况下,如果在上一个任务的已解析承诺中返回下一个任务的参数,则解析器将使用正确的参数并以正确的顺序调用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'); });

答案 2 :(得分:1)

使用 q 请求

的示例代码
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方法:获取发布

我正在使用request库。

  • 我的帖子 api方法,使用request.post()返回的响应对象的正文解析承诺。
  • 我的获取 api方法,使用request.get()调用的响应解析承诺

你可以确切地看到如何使用promises链接这些2 api调用。

在第一个然后中,我返回第二个承诺,以便我可以将承诺链接起来。