What Is the Correct Terminology for JavaScript Promises

What is the correct terminology for javascript promises

Terminology can be hard.

Let's take from the Promises/A+ specification and the respective ES6 section that there are 3 states:

  • pending - the promise does not have taken a value yet, it's future is still uncertain.
  • fulfilled - the promise successfully got a result value "assigned"
  • rejected - the promise is given a reason why no result could be acquired, typically an error.

The term settled is a hyperonym for fulfilled and rejected, meaning either - the opposite of pending.

The dynamic verbs fulfill and reject describe changing the state from pending into either the fulfilled or rejected. These transitions are called fulfillment or rejection of the promise.

Those were easy. Now, resolve is a different beast. It sometimes is used synonymous to "fulfill", but it would better be understood as settling the promise's fate to either fulfilled or rejected. The resolution (seldom: settlement) of a promise means that it leaves the pending state. But not even that is accurate - the problem is the recursive nature of the Promise Resolution Procedure:

  • resolving a promise with a "plain" value means fulfilling it
  • resolving a promise with a promise (or thenable) means adopting its state:

    • resolving with a fulfilled promise is a fulfillment
    • resolving with a rejected promise is a rejection
    • resolving with a pending promise means waiting for its resolution

Yes, if a promise is resolved it might not even be known whether it's going to be fulfilled or rejected. But it means the fate is no longer undetermined, as it's bound to the promise that we resolved with (notice that you can resolve a promise only once).

Ignoring this special case, a resolved promise usually means a settled promise.
Sample Image

Or, to cite the ECMAScript 6 Specification:

A promise is resolved if it is settled or if it has been “locked in” to match the state of another promise. Attempting to resolve or reject a resolved promise has no effect. A promise is unresolved if it is not resolved. An unresolved promise is always in the pending state. A resolved promise may be pending, fulfilled or rejected.


and what the heck is defer?

Deferring a result means that you return an (asynchronous) promise for the result, and not the result directly (synchronously). And also return a deferred rejection instead of throwing synchronously.

Notice that "defer" is also used in some libraries (Q) as the method name to construct a Deferred object - see this answer on The differences between Deferred, Promise and Future for a good explanation.

Oh, and never trust variable names: defer might as well be an abbreviated "deferredObject".

JS Promises: Fulfill vs Resolve

Indeed, the resolve callback does not imply that the promise will be fulfilled.

The terms fulfilled, rejected, pending, settled, resolved and locked-in are defined in
the EcmaScript2015 specs, 25.4 Promise Objects:

Any Promise object is in one of three mutually exclusive states: fulfilled, rejected, and pending:

  • A promise p is fulfilled if p.then(f, r) will immediately enqueue a Job to call the function f.

  • A promise p is rejected if p.then(f, r) will immediately enqueue a Job to call the function r.

  • A promise is pending if it is neither fulfilled nor rejected.

A promise is said to be settled if it is not pending, i.e. if it is either fulfilled or rejected.

A promise is resolved if it is settled or if it has been “locked in” to match the state of another promise.
Attempting to resolve or reject a resolved promise has no effect. A promise is unresolved if it is not resolved.
An unresolved promise is always in the pending state. A resolved promise may be pending, fulfilled or rejected.

A short overview, where I will use the term "autonomous" as the opposite of "locked in". They are the two possible values for a promise's dependency situation:










































actiondependencystateresolved?settled?
new Promise((resolve, reject) => ...)autonomouspendingnono
...resolve(thenable)locked-inpending*yesno
...resolve(other)autonomousfulfilledyesyes
...reject(any)autonomousrejectedyesyes

What is a function that returns a promise called?

In the javascript community I've seen a function that returns a promise called being "thenable" enough times that I think "thenable" when I'm coding. It's a thenable function.

I like this name for a number of reasons:

1) Thenable describes the functional behaviour. If it returns a promise, you can call "then" on it.

2) It's unique. Promises aren't exactly monadic, so monad isn't appropriate. "Async" is more of a super class of functions and doesn't help describe the nature of a Promise. But "thenable" is uniquely Promisely.

3) I also like that it's not repeating Promise everywhere, (Promissory, Promisified, Promise Function, etc.) which is approaching a circular definition IMO. Being able to google one word which has one specific meaning is really nice.

How can a Promise be resolved and pending?

It's right there in the section you linked to:

A promise is resolved if it is settled or if it has been “locked in” to match the state of another promise. [...]

That other promises might still be pending. Lets take a look at an example:

var p = new Promise(resolve => setTimeout(resolve, 1000));
var q = Promise.resolve(p);

// At this point `q` is resolved / "locked in" but still pending
// because the `p` promise is also still pending.

// Only after the timeout has passed, the `p` promise will resolve/settle
// and `q` will assume the inner promises state.

Looks like Bergi wrote a pretty comprehensive answer around promise terminology: What is the correct terminology for javascript promises

Definition of a JavaScript promise and what is the difference to an event?

For the first view, they are very similar. In events, you have a callback function, and in Promise you have a callback-function. Even more, technically, you can do almost similar stuff which Promises do only with Events.

Events and Promises both useful for Async code. I will write some abstract code to try explain. For example, you have some async code, and after that, it should alert something.

function someAsyncFunction() {
setTimeout(function() {
// some long async logic here
console.log('What the hell is Promises?');
}, 2000);
}
someAsyncFunction();

Timeout here is Async, because it will run your code not in main tread and run it after some time, you not sure when exactly it happens (ofcouse here it's around 2s. less-or-more).

So now imagine, that you need to do something with result of async action. For example you have function AsyncResultCalculator and you need to run that function. What you will do? You have few choices:

  • Pass a callback function to async code and run your function AsyncResultCalculator when async code complete it's work
  • Define some Event (for example 'DoSomethingAfterAsync' event) and trigger that event after async code is finished or failed.
  • Use promises

All this variants as result, will do only one thing - run your function AsyncResultCalculator. So, why we have 3 different ways to do the same result? Because it's cool! It's just different techniques to do the same stuff, but they change difficulty of your code. Some ways make your code more complicated, some ways make your code larger, some ways make your code more elegant.

So, i think you know how to run callback functions or how to trigger event, but what about Promises? How to use them? Very easy. Let's go back to Async Timeout and look:

function AsyncResultCalculator(res) {
// calculate result of async action!!!
console.log(res + 1);
}

function someAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
// some long async logic here
resolve(55); // or reject
}, 2000);
}
}

someAsyncFunction().then(AsyncResultCalculator);

So, what the point to use Promises here? Just because it's modern style for async actions. With promises your code will be more elegant and more easy to read for different developers. Also, promises is useful because you can build a CHAIN of function like

someAsyncFunction()
.then(function(){ ... })
.then(function(){ ... });

But, of course, in some cases, it's not bad to use callbacks or events. For example, events is more useful, if you need to catch async result in some different JS file and you don't want to uses promises or callbacks in original file with async action.

All JavaScript language is mix of events, callbacks and promises ;D Use it with wise.

  • Use events for DOM events or some complicated situations.
  • Use promises for async actions
  • Use callbacks for sync actions or where you don't want to use Promises

I know what a javascript Promise is, but is there a name for a function that returns a Promise ?

Basically, no. There is not a canonical name for a function that returns a Promise. You can call it whatever you like so long as it is true to the idea that a Promise captures some asynchronous functionality. For example, "an asynchronous function".

However, I would suggest simply using "function that returns a Promise". This is most accurate when you consider that the function itself is not any different for its return value (as @DaveNewton said, the fact it returns a Promise is an implementation detail).

Understanding Promise constructor

In fact, the first argument of the promise constructor callback is called resolve, not fulfill.

When you pass a promise or thenable into resolve, its state will get adopted, all other values fulfill the promise directly. This means that exactly the logic you were describing is implemented right within resolve - and, as you said, you don't need the condition in the resolver callback.

And in fact, the standard specifies Promise.resolve to be implemented quite like

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


Related Topics



Leave a reply



Submit