passing call back functions to promise.then() - javascript

when the call back functions in the myFunction gets called is it when the caller function makes a call like this myFunciton.then ()? Can I say the first one triggers upon myFunction being resolved and second call back function is called upon failure of the myFunction?
myFunciton: function() {
const myPromise = myService.loadData(oParams);
myPromise.then(() => {
//do something
}, () => {
//do something else
});
return myPromise;
}

Promises are a state machine with several potential states: pending(The initial state), fulfilled, and rejected.
When you create a new promise you provide a callback that accepts two parameters both functions resolve and reject respectively. resolve to enter a state of fulfilled, reject to enter a state of rejected, and if the code your promise wraps throws an exception the promise will also enter a state of rejected. Upon being either resolved or rejected your promise will store the returned value for subsequent resolutions.
Now whenever you call myPromise.then, myPromise.catch, or providing a call back function. The promise internally checks it's state.
If the promise is pending, it will queue your handlers, and when a call to reject, resolve, or an exception is thrown it will iterate through the queued handlers and call the appropriate handler(Depending on whether it was resolved or rejected).
Now if the promise is already fulfilled or rejected, the promise will call the appropriate handler asynchronously.
Let's look at your code:
myFunction: function() {
const myPromise = myService.loadData(oParams);
// handlers are queued if myPromise is pending
// function passed to then is called asynchronously if resolved
// callback will be called asynchronously if rejected
myPromise.then(() => {
//do something
}, () => {
//do something else
});
return myPromise;
}
Now your question on when your callbacks will be called.
// This will trigger the execution of myService.loadData
// As pointed out in the comments above your callbacks will either be queued, or
// called asynchronously.
// The value of myPromiseResult will always be a promise(pending, resolved, or // rejected)
const myPromiseResult = myFunction();
// Here's the cool part, since promises are essentially a state machine
// every subsequent callback will yield the same result
myPromiseResult.then(() => {
// if the callback pass to myPromise.then is called within myFunction
// this will be called as well, and if you were passing a result
// it would have the same result as well
}, () => {
// if the error callback pass to myPromise within myFunction was called
// then this will be called as well, and as mentioned above would have
// been passed the same result as well.
});

With that code, the first promise that will be resolved will be the one inside "myFunciton" function. Then, if you used something like myFunciton.then(), it will be resolved in second place.
I hope i could help you.

Related

Resolve await when message arrives

I have some websocket code in JS. I have a message-handling loop like this:
socket.addEventListener('message', function (event) {
payload = JSON.parse(event.data)
method = payload.method
// Dispatch messages
if (method == 'cmd1') {
handle_cmd1(payload); // trigger event/semaphore here to wait up waiter
}
else if (method == 'cmd2') { ... }
});
And elsewhere, I have a button callback like this:
$('#my-button').change(function() {
handle_button();
});
async function handle_button() {
send_msg('msg1', 'hi');
// wait for server to reply with cmd1
cmd1_data = await something(); // what?
alert(`cmd1 data: $(cmd1_data)`);
}
The idea is that the button sends 'msg1' and the server is supposed to reply with 'cmd1' and some info. I want to wait for that reply and then do some more stuff.
So my question is how to interlock these? In C++ I'd use a semaphore. I'd rather not spin-loop; is there something in Javascript/JQuery I can use to trigger and then wait for a user-defined event like this? I'm sort of new to JS, and very new to JS async/await.
EDIT: I've made a simple jsfiddle to show what I'm after.
http://jsfiddle.net/xpvt214o/484700/
Now that I understand how promises in Javascript work, here's a working example of a promise that can get woken up from anywhere by calling a function:
wakeup = null;
// returns a promise that will be resolved by calling wakeup()
// (could be a list of these or whatever, this is just a simple demo)
function wakeable() {
return new Promise( (resolve) => {
wakeup = () => { resolve(true); }
});
}
// demo of waiting and getting woken up:
async function handle_event() {
while (true) {
console.log("waiting...")
await wakeable(); // returns to event loop here
console.log("handle event woke up!");
}
}
handle_event(); // start in "background"
wakeup(); // wake it up
setTimeout(_ => { wakeup(); }, 500); // wake it up again after a delay
What's happening here is that when you call wakeable(), it returns a promise. That promise is constructed with an anonymous function (the one taking resolve as arg); the promise constructor synchronously calls that function, passing it the promise's resolve method. In our case, the function sets wakeup to another anonymous function that calls the original resolve; it's a closure so it has access to that resolve function even when it's called later. Then it returns the new promise.
In this demo, we then await on that promise; that puts the pending promise on a queue, saves the current function state, and returns, like a generator calling yield.
A promise is resolved when its resolve function is called; in this case calling wakeup() calls the promise's internal resolve() method, which triggers any .then methods on the next tick of the Javascript event loop (using the promise queue mentioned above). Here we use await, but .then(...) would work the same way'
So there's no magic; I/O and timeout promises work the same way. They keep a private registry of functions to call when the I/O event or timeout happens, and those functions call the promise's resolve() which triggers the .then() or satisfies the await.
By the way, unlike async in python, leaving a pending promise "open" when the process exits is perfectly fine in Javascript, and in fact this demo does that. It exits when there's no more code to run; the fact that the while loop is still "awaiting" doesn't keep the process running, because it's really just some closures stored in a queue. The event loop is empty, so the process exits (assuming it's in node.js -- in a browser it just goes back to waiting for events).
something() should be a method that returns a promise() or should be another method that is also notated with async.
function something(){
return new Promise(resolve,reject) {
//... call your database
// then
resolve(theResult)
// or
reject(theError)
}
}
The async and await for the most part are really just wrappers around promises. The await returns when the promise calls resolve, and throws an exception when the promise calls reject.
Your async function can return another promise; If it returns another value, it gets turned into a resolved promise with that value.

Javascript Promises-Dynamic Callbacks

I was reading this article on promises http://www.html5rocks.com/en/tutorials/es6/promises/ In which he mentions the following point
"If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier"
I'm not clear about this point. My Question here is,if a promise had already succeeded and later at some point if i add a callback ,how can this callback execute even though the event took place earlier
Please explain
Thanks
Sahithi
The promise knows whether it was resolved or rejected. So if you attach another event handler to it, it will call it appropriately.
For example:
function myFunc(){ return Promise.resolve();}
var myPromise = myFunc();
myPromise.then(function(){console.log('I resolved.');});
myPromise.then(function(){console.log('Me too!');});
Would result in:
I resolved.
Me too!
When you call .then() on a promise, it has one of three possible things to do depending upon whether the promise is already resolved, rejected or still pending.
If the promise is currently pending (not resolved or rejected), it can queue the passed-in .then() handlers for later use when the promise is actually resolved or rejected.
It can see that the promise is already resolved so it can schedule the resolveHandler that was passed in to run as soon as the stack unwinds
It can see that the promise is already rejected so it can schedule the rejectHandler that was passed in to run as soon as the stack unwinds
Imagine this pseudo code to illustrate:
Promise.prototype.then = function(resolveHandler, rejectHandler) {
var self = this;
if (this._promiseState === "pending") {
// promise is not yet resolved or rejected so
// just queue the .then handlers for later use
this._handlers.push({resolve: resolvehandler, reject: rejectHandler});
} else if (this._promiseState === "resolved") {
// already resolved, schedule the resolve handler to run
// immediately after stack unwinds
if (resolveHandler) {
setImmediate(function() {
var p = resolveHandler(self._resolvedValue);
// further processing
});
}
} else {
// already rejected, schedule the reject handler to run
// immediately after stack unwindws
if (rejectHandler) {
setImmediate(function() {
var p = rejectHandler(self._rejectReason);
// further processing
});
}
}
// more code here that eventually returns a new promise
}
If I understood your question correctly, this basically means that you can run a promise and after running it, set the callback.
In event-oriented programming, you must first set the event callback, otherwise if triggered it'll never do the proper callback.
With promises, you can run a promise someFunc() and later add the callbacks, regardless of when the promise is fulfilled in runtime.

Javascript Promises how to do post resolution cleanup

I am struggling with how to handle this special case. I know I could solve this with chained callbacks, but it seems like almost a poster child for promises:
I have a parent method that needs to execute three async things in order (specifically getting confirmation from a user). We'll call them func1 func2 and func3. Now I can have each of these return a promise and chain those and that is all working great. The issue I run into is:
func1 needs to set a state, wait on the rest of the chain to run, and then unset that state.
demonstration pseudocode:
function wrapper(){
func1()
.then(func2())
.then(func3());
}
function func1(){
return new Promise(function(resolve, reject){
//do some async stuff that itself returns a promise :)
async1().then(function(value){
//set some global states based on the value for the duration of this chain
resolve(); //Note NOT returning value as it's irrelevant to the other functions
//!!! clean up the global states regardless of future failure or success, but after one of those.
}, reject); //if async1 rejects, just pass that right up.
});
}
function func2(){
//do some logic here to decide which asyn function to call
if (/*evaluates to */true){
return async2(); //another async function that returns a promise, yay!
} else {
return async2_1(); //also returns a promise.
}
}
function func3(){
//do some dom updates to let the user know what's going on
return Promise.resolve(async3()).then(function(){
//update the dom to let them know that everything went well.
});//returns this promise chain as a promise which the other chain will use.
}
The part I'm struggling with is the line in func1 after resolve(); Note that as said there async1 which I'm calling in func1 does return a promise so I am already working with promises a lot here. I need the cleanup to happen AFTER the promise returned from func3 resolves.
Ideally this would all be contained in func1 in some way, but I'm also ok with a semi-global variable (this entire block will be wrapped in a larger function).
You'll want to use the disposer pattern (and avoid the Promise constructor antipattern):
function with1(callback) {
return async1() // do some async stuff that itself returns a promise :)
.then(function(value) {
// set some global states based on the value for the duration of this chain
const result = Promise.resolve(value) // or whatever
.then(callback);
return result.then(cleanup, cleanup);
function cleanup() {
// clean up the global states regardless of the failure or success of result
return result;
}
});
}
You can use this like
function wrapper() {
with1(() =>
func2().then(func3) // whatever should run in the altered context
);
}

What happens if a promise completes before then is called?

Let's say I have a Promise like this:
var promise = new Promise(function(resolve, reject) {
// Do some async thing
});
promise.then(function(response) {
// Then do some other stuff
});
What happens if the async Promise completes before I call .then()? Normally, I'd only have long running tasks in the Promise function, but what if it completes really quickly one time?
As expected: then callback will get called immediately in this case if then was called after promise has already resolved.
It's easy to test:
var promise = new Promise(function(resolve, reject) {
resolve(123);
});
setTimeout(function() {
promise.then(function(response) {
alert(response);
});
}, 1000)
As others have already pointed out, you can add callbacks with .then before or after the promise has been resolved, and you can even add more than one callback.
These callbacks will be called in the order they were added, but always asynchronously, after the current turn of the event loop. So if the promise has already been resolved when you add a .then, your handler will be called immediately, but in the "ascynchronous sense".
The Promises/A+ spec says:
[...] onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack.
A promise has state, which means that even after the promise gets fulfilled, you can attach callbacks using .then to it, and they will be called, with the same result as if the promise was fulfilled after they were attached.
Fulfilled is the final state of a successful promise. This means that you can attach more handlers to the fulfilled promise in the future, using the promise as a cache for the original response.
.then() on MDN
then()
Calls one of the provided functions as soon as this promise is either
fulfilled or rejected. A new promise is returned, whose state evolves
depending on this promise and the provided callback functions.
The appropriate callback is always invoked after this method returns,
even if this promise is already fulfilled or rejected. You can also
call the then method multiple times on the same promise, and the
callbacks will be invoked in the same order as they were registered.
The then callback will never get called before the promise is resolved, which is what I think you mean by complete. However, if a promise is resolved before it is returned from a function, any additional success callbacks chained after that moment will still be executed. For example,
function getMeAResolvedPromise() {
var prom = new Promise();
prom.resolve('some val');
return prom;
}
...
getMeAResolvedPromise.then(function(result) {
// this will still be executed
});

Understanding JS Promises

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.

Categories