Serial execution with Q promises

拟墨画扇 提交于 2019-12-08 22:15:55

问题


I think I'm misunderstanding how Q promises work. I want my first promise to resolve before the next one starts, but that's not happening. Here is my code:

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'); });

This code produces:

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

I would hope that it produces:

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

What am I doing wrong?


回答1:


This works:

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

That makes sense - just calling doWork directly in then() will fire off the timeout immediately, instead of giving Q a chance to wait until task one is complete.




回答2:


The reason is that the doWork needs to be referenced as a function. If you want to reference a function inside the '.then' then you just give the function name, you don't pass the parameters. When the parser sees .then(doWork('taskTwo'))it will run doWork('taskTwo') BEFORE the .then is even evaluated. It's trying to bind the function parameter.

In this case, if you return the parameter for the next task in the resolved promise of the previous task then the parser will call doWork with the correct parameter and in the correct order.

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:


Sample code using q and request

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

In the code above, you can see that I define 2 API methods: get and post.

I'm using the request library.

  • my post api method, resolves the promise with the body of response object returned by request.post()
  • my get api method, resolves the promise with the response of the request.get() call

You can see exactly how you can chain these 2 api call using the promises.

In the first then I return the second promise, so that I can chain the promise.



来源:https://stackoverflow.com/questions/15350587/serial-execution-with-q-promises

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!