Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
233 views
in Technique[技术] by (71.8m points)

javascript - `resolve` and `reject` functions inside a Promise's executor

Given that the client programmer both defines and uses the resolve function passed to the executor of a Promise, I naively assumed that I fully control the signature of the resolve function and so I can define it to take more than one arguments.

Yet the following code (jsFiddle) fails:

<html>
  <script>
   const promise = new Promise(function executor(resolve, reject) {
     setTimeout(function () {
       resolve(42, true);
       }, 1000);
   });
   promise.then(function resolveCallback(answer, howCertain) {
     console.log('callback called with arguments: ('+answer+', '+howCertain+')');
     console.log('the answer is: '+answer+'. I am '+(howCertain?'very':'not very')+' certain about that');
   });
  </script>
</html>

The above code actually prints on the console:

callback called with arguments: (42, undefined)
the answer is: 42. I am not very certain about that

Digging a little deeper, I wrote the below code (jsFiddle):

<html>
  <script>
   const promise = new Promise(function executor(resolve, reject) {
     console.log('entering executor, resolve is: ['+resolve+']'.);
     setTimeout(function () {
       console.log('about to call resolve');
       resolve(42);
       console.log('returning from resolve');       
       }, 1000);
   });
   console.log('about to call "then"');
   promise.then(function resolveCallback(answer) {
     console.log('the answer is: '+answer);
   });
  </script>
</html>

which actually prints the following on the console:

entering executor, resolve is: [function t() { [native code] }]
about to call "then"
about to call resolve
returning from resolve
the answer is: 42

This demonstrates a number of interesting things:

  • the executor is called before the client programmer has a chance to call then on the promise. And yet, the resolve parameter in the executor function is not undefined.
  • the resolveCallback function that is passed as argument in the call to then is not the same as the resolve function passed to the executor. Moreover, it is not executed synchronously (i.e. not in the same event loop run) with the resolve call from within the executor function.

The only way for Javascript to pull this off (that I can think of) is that the implementation is actually plugging some sort of "proxy" resolve and reject functions which are asynchronously linked to the actual resolve and reject functions supplied by the client programmer. This would also explain why you can't define your own signature for the resolve and reject functions: because the plumbing won't work.

Is this mental model correct or am I missing something?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The client programmer defines the resolve function passed to the executor of a Promise

No, he doesn't (as your experiment confirms). The executor is called during the new Promise creation.

When I call then on the promise, don't I pass a resolve function of my choosing?

No, you pass an onResolve listener callback, or actually an onFulfill callback.

Is my new mental model correct?

Yes, there is more plumbing below the surface.

Indeed, the new Promise constructor is giving you just proxy resolver functions.

A promise contains a state machine. It is an object representing an (one!) asynchronous result. As such, you can call .then() as many times on the same promise object, and the callbacks will always get passed the result.

It is not a wrapper around the executor function, it does not call the executor as often as you call then. The executor is called just once, to give the producer access to the resolver functions (the input of the state machine). The consumers that call then, watching the output of the state machine, are completely decoupled from this - as you say, they are asynchronously linked.

Also have a look at this. For your mental model, this is an easy-to-understand implementation of the Promise class (sans guaranteed asynchrony and error handling).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...