What this piece of JS code is doing exactly [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
This is sample code from here
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10);
console.log(x); // 10
}
f1();
I have few questions:
What is the resolve in the Promise constructor, and what resolve(x) do exactly?
What is asynchronous code? is it the call to resolveAfter2Seconds or just the code inside resolveAfter2Seconds (that is: the promise execution, while resolveAfter2Seconds returns immediately?

What is the resolve in the Promise constructor, and what resolve(x) do exactly?
The Promise constructor takes a callback function called executor. That executor callback will be called with two parameters. This call is made by the constructor itself. Both of parameters that will be passed in are functions:
resolve - when called will fulfill* the promise, marking it as successfully completed. The argument passed to the resolve function will become the value for that promise.
The value for the promise will be passed to .then() callback. If the promise is awaited the result is the value of the promise.
reject - when called will reject the promise, marking it as unsuccessfully completed. The argument passed to the reject function will become the reason that promise was rejected.
The reason for the rejection will be passed to .catch() callback. If the promise is awaited the reason is thrown and can be caught in a try/catch block.
Quick note: as with all parameters, these two can be given any name. The resolve and reject are very common ways of naming the functions.
* not necessarily true if passing another promise. If a another promise is passed, the current promise will adopt that promise's completion state. So, if resolve is called with a promise that is later rejected, the current promise will also be rejected.
The executor is then called immediately and the promise will be pending until either resolve or reject is called.
In your case the executor is:
resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
}
Which means that resolve is going to be called 2 seconds later with the value for x making that the value for the promise.
The await will suspend the execution of f1() and resume it when promise returned by resolveAfter2Seconds(10) settles. The result of await resolveAfter2Seconds(10) is the value of the promise. Which is 10 as you can see in the log.
What is asynchronous code? is it the call to resolveAfter2Seconds or just the code inside resolveAfter2Seconds (that is: the promise execution, while resolveAfter2Seconds returns immediately?
I would say that for practical purposes, asynchronous code is anything that will finish later than the normal top-to-bottom execution of code:
console.log(1);
console.log(2);
console.log(3);
async function later(x) { return x; }
console.log(1);
later(2).then(value => console.log(value));
console.log(3);
You could definitely try to make an argument otherwise, however trying to pinpoint exactly where async code starts and ends is not very useful. It runs the risk of turning into something that resembles Sorites paradox. If fn1 is not async code, then is it calling fn2 which lies inside? Or is it fn3 which is inside fn2? Etc. Hence my proposed more practical solution. If a function causes some effect to come up later than the current run-to-completion cycle we can say that it is asynchronous. So, any function that returns a promise (which includes all async functions) are asynchronous.
You can also see my answer here which discusses various asynchronous functions more.
Further reading:
What is the correct terminology for javascript promises - very important as it explains the fundamental concept of promises.
`resolve` and `reject` functions inside a Promise's executor
How is a promise/defer library implemented?
Concept - Distilling how a promise works?

Related

Typescript async generic function

I'm new to TypeScript and I have an async function like the one below. Can someone explain what it does and where resolve comes from? I hope I'm providing enough information for this.
async function SendMessage<T extends WorkerResponse>(msg: { id: number }): Promise<T>
{
const response = await new Promise<WorkerResponse>(resolve =>
{
waitingMessages.set(msg.id, resolve);
worker.postMessage(msg);
});
return response as T;
}
When I hover the mouse over the variables I get these:
(parameter) resolve: (value: WorkerResponse | PromiseLike<WorkerResponse>) => void
const waitingMessages: Map<number, (response: WorkerResponse) => void>
resolve comes from the Promise constructor. The Promise constructor calls the function you give it (the executor function) with two arguments. When defining an executor function, we idiomatically name the parameters to receive those arguments resolve and reject:
resolve - Resolves the promise (which may or may not fulfill it — here's my blog post on Promise terminology)
reject - Rejects the promise
The purpose of the code in the executor function is to start whatever asynchronous process the promise will report on, and then (when that process concludes), either: 1) use resolve to fulfill the promise, 2) use resolve to resolve the promise to another promise, or 3) use reject to reject the promise.
The async function you've shown does this:
Calls new Promise.
The Promise constructor calls the executor function passed to it synchronously, giving it access to resolve and reject functions. The one you've shown optimistically (and probably incorrectly) only uses a resolve parameter.
The executor code calls waitingMessages.set(msg.id, resolve);, which presumably sets up an eevn handler passing resolve as the handler implementation, and then worker.postMessage(msg); to send the message.
The code awaits the promise. (Which makes SendMessage return the promise it implicitly creates; it'll settle the promise it returns later.)
At some point, presumably the event gets fired and waitingMessages calls resolve, which probably fulfills the promise with some value (a fulfillment value).
Because the promise is fulfilled, the await is satisfied, and response gets assigned the fulfillment value of the promise that was awaited.
SendMessage's code returns that value, which fulfills the promise SendMessage implicitly returned, using the response value as the fulfillment value of that promise.
I've avoided going into too much detail above, but that's the gist.
None of this is specifically related to TypeScript, it's just how JavaScript promises work.
I suggest reading through Using Promises on MDN or any good Promise introductory tutorial or book.
As you can see he is building a new Promise object , which takes as parameter resolve and reject .
In this case as you can see it's returning the resolve function this is as saying Promise.resolve() with some values inside of it . But you are resolving and it's returning this object
{
waitingMessages.set(msg.id, resolve);
worker.`enter code here`postMessage(msg);
});
question is not really related to typescript but to javascript promise concept and async await .
What it does is that it creates a Promise, which provides you with a resolve function that you can run to mark the promise as fulfilled. If you await the SendMessage function, the code execution will stop until the resolve function is run.
It seems to add a message ID to some form of messages queue, and then send the message via a web worker. You can read more about web workers here
const result = await SendMessage(yourMessage);
console.log('These console.logs will not be run until something in your code..');
console.log('..executes the resolve function that was being stored via waitingMessages.set');

Race condition issues with async functions Javascript [duplicate]

I would like to get a deeper understanding of how Promises work internally.
Therefore I have some sample code:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Here a link to execute this code.
As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.
But the API ref states the following:
"then" returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Promise.resolve
So it would be interesting to know WHEN exactly the "then" function is executed?
Because the final "then" in the code is chained to the chainPromises(), I first thought that
it would execute after the function chainPromises() returns something (in this case another promise).
If this would have been the case the "val" of the final "then" function would be the returned promise.
But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved.
This absolutely makes sense because in this way, the "then" functions can be stacked, but
I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.
Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.
I hope I could make clear what I mean.. :)
About Promise resolution
The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:
onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
The ES6 promise specification (promises unwrapping) contains a similar clause.
This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.
In practice
This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.
This means the following:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
So for example:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
And that:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Is it a good idea?
It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.
In other languages
It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.
Let's start with an easy perspective: "chainPromises" returns a promise, so you could look at it this way:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Generally speaking, when returning a promise from within a "then" clause, the "then" function of the encapsulating promise will be marked as finished only after the internal "then" has finished.
So, if "a" is a promise, and "b" is a promise:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
So the output will be:
B!
Done!
Notice btw, that if you don't "return" the internal promise, this will not be the case:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Here we can't know what would be outputted first. It could be either "B!" or "Done!".
Please check the below example regarding how promises works:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1: shoe ticket');
console.log('person2: shoe ticket');
const promiseGirlFriendBringingTickets = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ticket');
}, 3000);
});
promiseGirlFriendBringingTickets.then((t) => {
console.log(`person3: show ${t}`);
})
console.log('person4: shoe ticket');
console.log('person5: shoe ticket');
Promise then return promise object, not promise's resolved value. I forked your JsFiddle, and added some of mine try this.
promise.then is executed right after that promise object is resolved.
I do not know how this is done in actual promises libraries, but I was able to re-create this functionality in the following way:
1) each promise has a waitingPromises property;
2) then method returns a new promise, and the original promise's waitingPromises property points to the new promise.
In this way, the chain of .then()s creates a structure that is similar to a linked list or rather a tree (each promise can have several waiting promises). A promise can be resolved only after its 'parent' promise has been resolved. The .then method itself is executed immediately, but the corresponding promise that it creates is resolved only later.
I am not sure this is a good explanation and would love to learn about other possible approaches.
Normally code is synchronous - one statement executes like (fileopen) and there is a guarantee that the next statement will execute immediately afterwards like filewrite()
but in asynchronous operations like nodejs, you should assume that
you have no idea when the operation will complete.
You can't even assume that just because you send out one request first, and another request second, that they will return in that order
Callbacks are the standard way of handling asynchrnous code in JavaScript
but promises are the best way to handle asynchronous code.
This is because callbacks make error handling difficult, and lead to ugly nested code.
which user and programmer not readble easily so promises is the way
You can think of Promise as a wrapper on some background task. It takes in a function which needs to be executed in the background.
The most appropriate place to use a promise is where some code is dependent on some background processing and it needs to know the status of the background task which was executed. For that, the background task itself accepts two callback resolve and reject in order to convey its status to the code which is dependent on it. In layman terms, this code is the one behind it in the promise chain.
When a background task invokes resolve callback with some parameter. it's marking the background operation successful and passing the result of the background operation to the next then block which will be executed next. and if it calls reject, marking it as unsuccessful then the first catch block will be executed.
In your custom promise, you can pass an error obj to the reject callback so that next catch block is aware of the error happened in the background task.

What's the purpose of the promise object that gets returned by the .then() method?

I have read on multiple websites, that the .then() method from the promise.prototype returns a promise. Unfortunately, no source describes the reason behind this.
The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise. - developer.mozilla.com
Why/When would someone need this returned promise object, how is this promise object related to the original object.
Thanks a lot for helping.
A promise is executed asynchronously, you never know when the then() will be executed.
And a promise can return a promise, this allows you to chain asynchronous events handling in singles lines of code.
Example code given by Mozilla:
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
It avoids the "pyramid of doom" :
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
There are three main aspects to the fact that .then() returns a promise.
The first is that you can chain operations like this:
a().then(b).then(c).then(d)
Because .then() returns a new promise, the following .then() handlers will not be executed until that new promise resolves. If b and c are synchronous, then that new promise will resolve when they return and the chain will continue when first b is done and then when c is done.
The second is that the new promise can be influenced by what the .then() handler returns. This allows b, c and d to be asynchronous operations that, themselves returns promises and the chain will be sequenced appropriately. So, imagine that b and c both return promises themselves.
First you get a() returning a promise. When that resolves resolves, its .then() handler gets called. That will then run b. If b() is also an async operation and it returns a new promise, then the promise that a.then(b) returns that all the other .then() handlers are linked to will NOT be resolved until that new promise that b returned is resolved. This allows a .then() handler to insert a new asynchronous item into the chain. This is a very important aspect of chaining promises. .then() handlers can insert them own asynchronous operations into the chain and they can even do it conditionally based on prior results or current state.
If a().then(b) just returned the same promise that a() returns, then all the subsequent .then() handlers would not be able to "wait" for the promise that b() returns because they would have been linked to the a() promise and it has already resolved. It is the returning of this new promise that allows the function inside the .then() handler to influence the subsequent chain because that new promise is influenced by what the .then() handler returns.
The third aspect is that the return value of the .then() handler can influence the resolved value of the new promise and that is what is passed to the next .then() handler in the chain. If a().then(b) just returned the same promise that a() returns, then all the subsequent .then() handlers would just see the same resolved value from a() because that resolved value was already set when a() resolved which is before a().then() has called its .then() handler. These subsequent .then() handlers wouldn't be able to inherit a new resolved value from then code inside the .then() handler.
Let's look at a specific scenario. I'll use a delay method as a simple example of a function that returns a promise that resolves in the future.
function delay(t, val) {
return new Promise(resolve => {
setTimeout(() => resolve(val), t);
});
}
Then, define several different async functions:
function a(val) {
return delay(100, val + 1);
}
function b(val) {
return delay(50, val + 10);
}
function c(val) {
return val * 100;
}
Now, put them all in a chain:
a(100).then(b).then(c).then(val => {
console.log("all done: ", val);
});
Here's what happens step by step:
a(100) is called. This calls delay (which sets a timer) and returns a promise which I will call a1_promise just for purposes of describing things here.
Then, because we're doing a(100).then(b), we take the return value from a(100) which is the a1_promise and call a1_promise.then(b). That stores away the b function as a .then() handler function to be called sometime in the future when a1_promise is resolved (not right now). That then returns a new promise which I will call a2_promise.
Then, because we're doing a(100).then(b).then(c), we take the return value from a(100).then(b) which is the a2_promise and call a2_promise.then(c). That stores away the c function as a .then() handler function to be called sometime in the future when a2_promise is resolved (not right now). That then returns a new promise which I will call a3_promise.
Then, because we're doing a(100).then(b).then(c).then(...), we take the return value from a(100).then(b),then(c) which is the a3_promise and call a3_promise.then(c). That stores away our last anonymous function as a .then() handler function to be called sometime in the future when a3_promise is resolved (not right now). That then returns a new promise which I will call a4_promise (which nobody uses).
Now we're done with synchronous execution. Note that a().then(b).then(c).then(...) was all executed synchronously. All three .then() methods have already been called on all the different promises. But, because NONE of the promises created here are yet resolved, none of the .then() handlers have actually been called yet. They've all just been stored away to be called in the future when the promises are resolved.
Now some time passes and the timer created inside of a() fires and resolves a1_promise. That then triggers a1_promise to call any .then() handlers it has and pass it the resolved value of the a1_promise which in this case will be 100 + 1 or 101. Since there is just one .then() handler on the a1_promise and it is the b() function, it will call b(101) now. Executing that will just return a new promise which b() created and returned. We will call that new promise b_promise. Inside the a1_promise() it knows that it created the a2_promise() when a1_promise.then() was previously called so it knows that when it executes that stored .then() handler and that .then() handler executes and returns a new promise, then it holds off on resolving the a2_promise that it created until thatb_promiseis resolved. In this way, you can see that further execution of the chain is now controlled by theb_promise, thus the code executing inb()and the promise is returned are inserted into thea().then().then().then()chain holding off future.then()handlers until theb_promise` is resolved.
Now some more time passes and the timer created inside of b() fires and resolves the b1_promise with a newly modified value of 101 + 10 which is 111. This tells the a2_promise that it can now resolve with that value.
The a2_promise can then call it's .then() handler and can execute c(111) which again just like in step 6 returns c_promise which is not yet resolved.
Some time passes and c_promise resolves with a value of 111 * 100 which is11,100. That tells thea3_promise` that it can now resolve with that value.
The a3_promise can then call it's .then() handler which is our arrow function at the end of the chain and we get a console.log() showing 11000 as the final value.
This is the good part of a Promisse.
You can chain a lot of methods where which one depends from a method result (in this case Promisse.resolve) above, for example. Like this

Where is code executed asynchronously in a Promise?

The following javascript function is from You Don't Know JS: Async & Performance. According to my understanding, the first comment // start doing something that could take a while is misleading. The section of the code where something is actually done possibly asynchronously is in the function passed into the Promise constructor.
function foo(x) {
// start doing something that could take a while *misleading comment*
// construct and return a promise
return new Promise( /* executor */ function(resolve,reject){
// eventually, call `resolve(..)` or `reject(..)`,
// which are the resolution callbacks for
// the promise.
} );
}
I would fix it in the following way:
function foo(x) {
// construct and return a promise
return new Promise( /* executor */ function(resolve,reject){
// start doing something that could take a while
// then foo returns the newly created Promise
// eventually, call `resolve(..)` or `reject(..)`,
// which are the resolution callbacks for
// the promise.
} );
}
Yes, this should be fixed (thanks for filing this issue).
This reminds me a bit of the difference between the deferred pattern and the revealing constructor pattern. Starting the asynchronous task inside the promise constructor callback has two advantages:
If it throws synchronously (e.g. a syntax error, a typo in the method invocation etc), the exception will be caught implicitly and reject the promise
The resolve and reject callbacks are already in scope to be passed to the asynchronous process as callbacks.
The answer is: nowhere is code executed asynchronously in a promise. *
While the second form you show is slightly more advantageous, this is solely because it handles errors more consistently (expecting callers to handle both exceptions and rejections is poor form).
Addressing your main confusion: The promise executor function runs synchronously. From MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object).
And the spec:
Returning from the executor function does not mean that the deferred action has been completed but only that the request to eventually perform the deferred action has been accepted.
It is up to you to launch any asynchronous operation that eventually calls resolve or reject:
new Promise(resolve => setTimeout(resolve, 2000))
.then(() => console.log("Async"));
console.log("Sync");
Most importantly, the Promise constructor only exists to wrap legacy functions that don't support promises already. Don't use it for anything else.
*) Actually, .then guarantees that functions passed to it never run immediately, so my first statement isn't entirely correct. The soonest they can run is at the end of the same run of the event loop, in a micro-task queue. Hardly what you're after.

When or who does pass resolve and reject functions to JS promises?

I have begun learning javascript promises. But I just can't understand the concept of promises.
The thing that bothers me most is who is passing the Resolver and Reject function to a promise constructor ?
See this example of Promise:
function getImage(url){
return new Promise(function(resolve, reject){
var img = new Image()
img.onload = function(){
resolve(url)
}
img.onerror = function(){
reject(url)
}
img.src = url
})
}
Now who does pass resolve and reject methods, as my understanding of javascript says to me that this script will throw unknown variable errors as resolve and rejects are not defined?
getImage('doggy.jpg').then(function(successurl){
document.getElementById('doggyplayground').innerHTML = '<img src="' + successurl + '" />'
}).catch(function(errorurl){
console.log('Error loading ' + errorurl)
})
Now you see a method like the above, the only way these methods(resolve and reject) are passed are via then and catch as used in above method call to getImage.
The thing that bothers me most is who is passing the Resolver and Reject function to a promise constructor ?
Nobody.
The functions are passed by the promise constructor.
They are passed to the function which you pass as the first argument to the promise constructor.
The Promise constructor is initialized with a callback, and the constructor passes reject and resolve as parameters when the callback is called.
Here is a simple demo:
class PromiseDemo {
constructor(cb) {
cb(this.resolve.bind(this), this.reject.bind(this));
}
resolve(d) {
console.log('resolve', d);
}
reject(d) {
console.log('reject', d);
}
}
new PromiseDemo((resolve, reject) => {
Math.random() > 0.5 ? resolve('1') : reject('1');
});
I had the same problem in understanding Promises.You need to look at the process of promise creation carefully.
when you write
var promise= new Promise(function(resolve,reject){...})
you are actually invoking constructor of Promise class or creating an object of Promise class. Now Promise constructor requires a function callback.
Now resolve and reject are just function arguments and not any other values.
You can write anything in place of resolve or reject like resolveHandler or rejectHandler.
These resolve or reject are nothing but the function callback that Promise calls when Promise is executed.
Now resolve is called when Promise is executed successfully and reject is called when promise is executed with some error or unsuccessfully .
The argument with which resolve is called can be accessed inside then like this
getImage().then(function(valueSentInResolve){ console.log('')})
The argument with which reject is called can be accessed inside catch like this
getImage().then(function(valueSentInResolve)
{//..do something}
).catch(function(errorSentInReject){
console.log('error',errorSentInReject )
})
I hope that helps.Let me know if I said anything wrong.
I have been studying Promises all day, and had the same question. I finally figured it out.
When you make a Promise object, you give the Promise Constructor an executor, which can be any function, as long as it has this signature.
anyFunction(resolutionFunction, rejectionFunction){
// typically, some asynchronous operation.
}
So any function with 2 functions as the arguments can be used. The first function is what you call when it works, the second is what you call when it breaks. You can name those functions whatever you want as well.
The Promise Constructor takes the function you pass in and does a few things with it.
It takes those 2 function arguments and generates a corresponding pair of functions that are "connected" to the Promise object.
It runs the executor
It ignores any return value from your executor
Now in your executor function when the promise resolves you call the positionally first function and pass it one value. It will look something like:
resolutionFunction(value)
You may be wondering, where is resolutionFunction defined? Remember the Promise Constructor defined that function for us. So we can call resolutionFunction without having to define it ourselves. Behind the scenes, when we call that resolutionFunction generated by the Promise Constructor, it sets the state of the promise to fulfilled, calls the function inside the promiseObject.then function, and passes the value into the .then function so you can use it.
You would call the 2nd positional function if the promise failed and the same things would happen and you could deal with the failure.
This Mozilla Doc on the Promise Constructor was very helpful.
Here is a short examples that shows what I explained above.
function anyFunction(callThisFunctionWhenItWorks, callThisFunctionWhenItBreaks) {
let importantNumber = 10; //change to 11 if you want the promise to reject
if (importantNumber == 10) {
callThisFunctionWhenItWorks('Hooray, success, so we call resolved for the promise.');
} else {
callThisFunctionWhenItBreaks('Boo, rejected because important number is not equal to 10');
}
}
//make a new promise
const examplePromise = new Promise(anyFunction);
//use the promise
examplePromise.then(function(result) {
console.log(result);
}).catch(function (error) {
console.log(error);
})
The promise library creates and passes those functions, along with all the other metadata needed to track the promise and record completion, store state and progress, cancel it, etc.
The folks behind Bluebird have published some info on how the library works internally, and you can see more in the Bluebird source.
does this make sense? This explanation could be completely incorrect!!
We provide the logic which should run asynchronously. The logic should accept 2 functions, resolve and reject. The reference of these functions is provided by Promise. These functions should be called by our logic when we have the final value or error. The Promise created initially is in Pending state. Calling resolve and reject changes the state to Fulfilled or Rejected respectively.
executeFunction(res,rej) = {
do some op, say DB query.
if (success) res(value) //executeFunction uses the resolving functions to change state of the Promise. Calling res fulfills the promise with value
if (fail) rej(reason)//executeFunction uses the resolving functions to change state of the Promise. Calling rej rejects the promise with reason
}
Rather than calling executeFunction directly (which would make the call synchronous), we create a Promise will will run the executeFunction code in a separate thread (asynchronously) let p = Promise(executeFunction(res,rej));. We get back a reference of the Promise.
My guess is that internally in the Promise, the following happens
Promise(e(res,rej)) = {
// the Promise's constructor creates a new promise, initially in the pending state. It calls `e` (the executeFunction function) and provides references to the resolving functions to it that can be used to change its state.
state = pending;
e(_res,_rej); //starts my op. asynchronously (a new thread). Reference to resolving functions, _res, _rej is provided. _res and _rej are Promise's internal functions (see below)
//constructor doesn't return till the async thread finishes
}
_res (value){ //Promise's internal method
//probably sets the state of promise to Fulfilled and store the result of the Promise
state = fulfilled
resolvedValue = value;
}
_rej {//Promise's internal method
probably sets the state of promise to Rejected and store the result of the Promise
state = rejected
resolvedValue = error;
}
Creating the Promise starts the execution of the code asynchronously. Now we are interested in knowing what is the result of executeFunction (we don't care when executeFunction finishes). To do this, we call then of the Promise p. then takes two optional arguments and registers them as callbacks. I am not sure when and who calls these callbacks. I know that then returns another Promise but I am not able to understand how that works
then(executeFnIfPromiseResolved, executeFnIfPromiseRejected):Promise {
register executeFnIfPromiseResolved as callback
register executeFnIfPromiseRejected as callback
//NOT SURE WHO AND WHEN THE CALLBACKS ARE CALLED
//then needs to return Promise. What would be the executor function of that Promise?
}

Categories

Resources