2013-03-11 69 views
6

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

我在做什么错?

回答

7

这工作:

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

这是有道理的 - 只是打电话doWork直接then()将立即关火超时,而不是给Q上的机会要等到task one完成。

4

的原因是需要的doWork作为函数被引用。如果你想引用'.then'中的一个函数,那么你只需给出函数名称,而不传递参数。当解析器看到.then(doWork('taskTwo'))时,它将运行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'); }); 
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()调用

您可以看到如何使用承诺链接这些2 api调用。

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