Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between defer().promise and Promise

Tags:

I know defer separates promises states control and process, here using Q as an example, the promise returned by Q.defer().promise and Q.Promise is totally different, why designing in this way? and what's the difference between these two "Promise"

Thanks in advance

PS: I'm currently working on a Promise library, issuses and PRS are welcomed: https://github.com/jiananshi/Promise-polyfill

like image 906
jiananshi Avatar asked Feb 24 '15 03:02

jiananshi


People also ask

What is the difference between deferred and promise?

Deferred I was first introduced to Deferred using Python’s twisted library. Deferred is actually available in jQuery, and they are practically the same. The essence and core idea of Deferred is the same as Promise, but with a different presentation. You can see that Deferred and Promise are quite similar.

What is the difference between legacy deferred API and promise constructor?

The legacy defer API - in which you create a deferred that you can .resolve (value) and it has a promise you can return. The promise constructor - which is the modern API in which you create the promise from a completion source. Why do we need two APIs?

What is the difference between a promise and an object?

A “promise” is a promise that some action will be performed in the future. The biggest change is that it moves the passing of callback functions from parameters to return values. A Promise object means an unfinished job that is promised to be completed in the future, and expects a callback function.

What is a deferred?

A deferred is the work that must take place in order for a promise to “settle” (that is, for the promise’s ultimate value to be available). Like the action of painting that the artist needs to do before the judges could see the final product. Every deferred has a promise which functions as a proxy for the future result.


1 Answers

Well, this is about the promise resolution source. Q and a bunch of other libraries offer two APIs:

  • The legacy defer API - in which you create a deferred that you can .resolve(value) and it has a promise you can return.
  • The promise constructor - which is the modern API in which you create the promise from a completion source.

Roughly doing:

var d = Q.defer();
setTimeout(function(){ d.resolve(); }, 1000); 
return d.promise;

Is the same as:

return new Promise(function(resolve, reject){
   setTimeout(resolve, 1000);
});

so you might be asking

Why do we need two APIs?

Well, the defer API came first. It's how some other languages deal with it, it's how the papers deal with it and it's how people used it first - however - there is an important difference between the two APIs. The promise constructor is throw safe.

Throw safety

Promises abstract exception handling and are throw safe. If you throw inside a promise chain it will convert that exception into a rejection, quoting the spec:

If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason

Let's assume you're parsing JSON from an XHR request:

function get(){
    var d = Q.defer();
    if(cached) { // use cached version user edited in localStorage
        d.resolve(JSON.parse(cached));
    } else { // get from server
       myCallbackApi('/foo', function(res){ d.resolve(res); });
    }
}

Now, let's look at the promise constructor version:

function get(){
    return new Promise(function(resolve, reject){ 
        if(cached) { // use cached version user edited in localStorage
            resolve(JSON.parse(cached));
        } else { // get from server
           myCallbackApi('/foo', resolve);
        }
    });
}

Now, assume somehow your server sent you invalid JSON (or the user edited it to an invalid state) and you cached it.

In the defer version - it throws synchronously. So you have to generally guard against it. In the bottom version it does not. The top version usage would look like:

try{
  return get().catch(function(e){
     return handleException(e); // can also just pass as function
  });
} catch(e){ 
   handleException(e);
}

In the bottom version - the promise constructor will convert throws to rejections so it is enough to do:

return get().then(function(e){
   return handleException(e);
});

Preventing a whole class of programmer errors from ever happening.

like image 73
Benjamin Gruenbaum Avatar answered Nov 08 '22 01:11

Benjamin Gruenbaum