6

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

我究竟做错了什么?

4

3 回答 3

7

这有效:

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

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

于 2013-03-11T23:56:51.700 回答
4

原因是 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'); });
于 2013-05-28T16:04:44.800 回答
1

使用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

我正在使用请求库。

  • 的 post api 方法,使用request.post() 返回的响应对象的主体来解决承诺
  • 我的get api 方法,通过 request.get() 调用的响应来解决承诺

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

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

于 2015-06-11T15:22:44.110 回答