Polling with promises

I'm a big fan of promises in javascript. I think they are a cleaner way to express asynchronous operations than callback. They encourage re-use, are immutable and you don't care when your data is ready. Unfortunately, they are not well understood by the community, and few people are using it.

Here I want to show a quick example to do polling with promises. It came up at work a few days ago. We have to convert video to a given format. To do so, we're using a thirs party which does that. We submit it a job, and then we need to poll its api to see when the job is completed.

Here's the callback based implementation:

function poll(jobId, retry, cb) {
  if('function' === typeof retry) {
    cb = retry;
    retry = 5;
  }
  
  if(!retry--) {
    return cb(new Error('Too many retries');
  }
  
  api.getJobStatus(jobId, function(err, data) {
    if(err) return cb(err);
    if(data.state === 'finished') return cb(null, data);
    if(data.state === 'error') return cb(data.error);
    setTimeout(function() {
      poll(jobId, retry, cb);
    }, 10000); // retry in 10s
  });
}

Below is the variant using promises. I am using bluebird, a fantastic library for promises, which has a method to transform callback based apis into promise based.

var getJobStatusAsync = Promise.promisifyAll(api);

function poll(jobId, retry) {
  if(!retry) retry = 5;
  if(!retry--) throw new Error('Too many retries');
  
  return getJobStatusAsync(jobId)
  .then(function(data) {
    if(data.state === 'error') throw new Error(data.error);
    if(data.state === 'finished') return data;
    return Promise.delay(jobId, 10000).then(poll);
  });

And that's it, Promise.delay really helps to keep things clean.