1

I'm reading the Async & Performance book of the YDKJS series and am having trouble wrapping my head around the revealing constructor pattern.

Here's the example the book gives:

function foo(x) {
  // start doing something that could take a while

  // construct and return a promise
  return new Promise( function(resolve,reject){
    // eventually, call `resolve(..)` or `reject(..)`,
    // which are the resolution callbacks for
    // the promise.
  } );
}

var p = foo( 42 );

function bar(fooPromise) {
  // listen for `foo(..)` to complete
  fooPromise.then(
    function(){
      // `foo(..)` has now finished, so
      // do `bar(..)`'s task
    },
    function(){
      // oops, something went wrong in `foo(..)`
    }
  );
}

bar( p );

I have two questions:

  1. I think the intention is not to expose the resolve and reject logic to the outside, which creates a good separation of concern between the promise logic and what happens next with .then() in the function (in this case bar()) that "listens" to the Promise. Am I on track here?

  2. The example foo() confuses me. In the comment // start doing something that could take a while, what exactly is this? Is this where your async call would be? Shouldn't it be inside the function in the return statement? I don't understand how this would work otherwise.

Dan
  • 119
  • 7

2 Answers2

2

I think the intention is not to expose the resolve and reject logic to the outside, which creates a good separation of concern

Yes, that and the difficulty of catching exceptions in the deferred pattern, an alternative way to expose the resolvers only to the function that creates the task but not those that consume the result.

The example foo() confuses me. In the comment // start doing something that could take a while, what exactly is this? Is this where your async call would be?

Yes, that's what they meant.

Shouldn't it be inside the function in the return statement?

Yes, indeed it should be. A specific example might be

function delay(x) {
  return new Promise(function(resolve) { // construct and return a promise
    setTimeout(function() { // start doing something that could take a while
      resolve(); // eventually, call one of the resolution callbacks
    }, x);
  });
}

It's of course possible that starting the task and waiting for its result are two separate statements, so they could in theory be put apart:

function ajax(x) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", x);
  xhr.send(); // start doing something that could take a while

  return new Promise(function(resolve, reject) { // construct and return a promise
    xhr.onload = resolve;
    xhr.onerror = reject; // eventually, call one of the resolution callbacks
  });
}

but that is a bad practise, as when new, open or send throw you would not get a rejected promise back but an exception. So everything from var xhr = … should be inside the promise constructor callback.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
-1

For 2., in general and without further details, yes, you are correct; the resolver function passed to Promise constructor executes immediately. One exception would be use of async/await, though async/await does not appear at JavaScript at Question.

guest271314
  • 1
  • 15
  • 104
  • 177
  • Just to make sure I'm clear, you're saying that I'm correct in that the tasks you want to do that "take a while" (ajax, setTimeout, etc), should be inside the resolver (`new Promise(function(resolve, reject) { // stuff that takes a while goes here }`) – Dan Jul 26 '17 at 15:07
  • @Dan Yes, unless the authors have a reason for leaving the comment at that line of the piece. Have you asked the authors what the meant by the comment and why the placement of the comment at code is where it is? – guest271314 Jul 26 '17 at 23:20