Javascript promises not working in my case - javascript

Its a simple case
var q = new Promise(function(resolve, reject){
resolve(initRequest('get', 'includes/getRemessaRegistrada.php', null, remessasList));
}).then(function(){
console.log('ok');
});
I'm learning javascript promises concept. Why console.log('ok') is coming before resolve processing?

In your code initRequest() does not return anything. For your code to work as you have it, initRequest() must return a promise that is tied to the underlying asynchronous operation. And, if it did return a promise, then you don't need another wrapping promise around that.
Promises by themselves do not have magical powers to somehow know when an underlying asynchronous operation completes. They just don't have such powers. A promise only works when there's an asynchronous operation that calls resolve or reject on the promise at the appropriate time when the asynchronous operation completes with a value or an error. The promise then serves as an easier to use interface for managing and coordinating asynchronous results or errors.
You are running initRequest() which starts your async operation and then immediately returns, then long before it finishes, you are calling resolve(undefined) for your wrapping promise. This promise will resolve long before initRequest() is done and will not know anything about the async return value.
The best solution here would be to get or use a promisified version of XMLHttpRequest so you can make ajax calls with functions that just return promises. jQuery has one built in. The latest browsers have fetch() which does Ajax and returns a promise and there are dozens of small libraries available to do this or you could make your own. If you aren't already using a library that has this built in (like jQuery) and you need to get something specifically for this, I'd probably get a fetch() polyfill since this is clearly the future direction for browsers.
If you wanted just a simple XHR wrapper or a way to make ajax calls using a promise interface, here are some ways to go:
How do I promisify native XHR?
XR
Fetch Polyfill
It also occurs to me that because you have return req.responseText in your initRequest() function, you may think that initRequest() is returning that value. It is not. initRequest() returns nothing. return req.responseText is being returned to an async callback which just goes into the bowels of the XMLHttpRequest implementation. Your initRequest() function has long, long since already returned and returned undefined. For more on why this is the case, see How do I return the response from an asynchronous call?.

Related

does Javascript .then() function check for the promise in a web api

Thank you for reading this.
I'm really struggling with fully understanding how async programming works in Javascript.
Imagine this code:
Promise.resolve().then(randomcallback)
So in this scenario what I think would happen is the following: Firstly, in the normal call stack the Promise.resolve() function would immediately resolve a Promise object and return it. Then, the .then() function checks if the promise is resolved and if so it adds the randomcallback function to the microtask queue which when the call stack is empty gets executed and returns a new promise object.
But imagine if instead of calling the .then() function on a resolved promise object, we call it on a pending object. How is the then function able to check when the Promise object is resolved? Is it constantly checking in some web api thread like some event listener (since the rest of the program can run on) for the status property to be changed to fulfilled to then pass the callback function to the microtask queue?
The same for async await, does the await keyword just contact some web api to listen when the promise gets resolved? If so does it still do that if the promise object is already resolved at the beginning (no settimeout in it)
if you use:
randomunresolvedpromise.then(randomcallback)
let's say that randomunresolvedpromise gets fulfilled in 3 seconds (when callstack is empty)
how is the .then function even executed (also I've looked at the source code of the library, but it's really confusing since it uses so many callback functions) since the program literally keeps running and randomresolvedpromise only gets fulfilled when the stack is empty, is the function also just waiting in some sort of web api or what?
I've literally watched a lot of videos, read a lot of articles, but they don't seem to touch what really goes on in the event loop when using Promises and async and await.
It's all really confusing to me, I hope my question really makes any sense.
I really appreciate any answer, thanks!
How is the then function able to check when the Promise object is resolved?
It doesn't. The then method puts the callback on the promise's list of fulfillment callbacks, and then its job is complete. Later, when the promise is fulfilled, it's that code (fulfilling the promise) that puts calls to the promise's fulfillment callbacks in the microtask queue. (You're right though that it's then that does it when the promise is already fulfilled when then is called.)
await works the same way, since await is "just" syntactic sugar for then. (That "just" skips over a lot of details, though. :-D )
Side note: You'll notice I said "fulfillment callbacks," not "resolution callbacks," and referred to the promise being fulfilled (not resolved). There's a big difference between "fulfilled" and "resolved," but unfortunately it's not well understood and people use "resolve" where they mean "fulfill" a lot. See my blog post here (which the MDN folks linked from their documentation) for the difference (and why it matters). (That said, if you say you "resolve the promise with X" and X isn't a promise or other thenable, that's basically synonymous with "fulfill the promise with X." That's not true when X is a promise or other thenable.)

promise chain resolves before its last promise resolves

Background
Started with 2 nearly identical javascripts then refactored into 3: a utility script containing formerly redundant code + 2 calling scripts.
Problem
The two original scripts use jquery Deferreds (when.then) and work fine. The 3-script scenario fails because the next-to-last promise resolves early from one calling script.
Details
The first script, call it "multi" uses a sequence of deferreds to loop through a series of ajax requests and then refreshes the "multi" page in the browser. So:
auth -> user -> loop (updateIssue -> transition) end loop -> refresh
The 2nd, "single" uses effectively the same code without the loop, and then a different refresh function
My aim was to refactor the code into a promise chain in a utility script and use like so:
// calling script
Utility.promiseChain().done(refresh())
// utility script
Utility.promiseChain = function() {
return authPromise()
.then(function() { return userPromise();} )
.then(function() { return Promise.all(array of update.then(transition) promises);})}
The Problem, More Specifically
The Promise.all call ALWAYS resolves after update, but before transition, causing the refresh to fire early, followed by the transition. Any insight you can provide will be most helpful.
The Promise.all call ALWAYS resolves after update, but before transition
The only way that can happen is if something in your chain of events is not properly chaining promises. You will have to show us the real code for us to help you identify the specific problem, but if Promise.all() is not waiting for a transition promise, then that promise must not be properly chained into the array of promises that Promise.all() is waiting on.
Specifically, we need to see the code behind this part of your pseudo-code:
array of update.then(transition) promises
to see exactly how transition() is involved in creating that array of promises.
As always, if you show us your REAL code rather than just pseudo-code, we can help find the source of the actual error in programming logic.
A possible scenario is that you are using JQuery < version 3, and the call to authPromise() returns a JQuery promise. This would mean all the promises returned by then in the promise chain returned by Utility.promiseChain are JQuery promises. The last time I checked, older versions of JQuery do not recognize foreign library promises, including those returned by native Promise constructors, as a promise and will fulfill a JQuery promise resolved with one without waiting for it to be settled.
It is possible that the promise object returned by Promise.all in
.then(function() { return Promise.all( // ...
is being used to fulfill the promise returned by then without waiting for it to be settled.
In short you can't resolve an older version of JQuery promise with an ES6 promise and produce the effect of resolving a promise with a promise.
Potential solutions:
Upgrade to JQuery 3 (you lose support for old versions of IE but these don't support Promise anyway). Recommended if you can do it.
Convert all promise usage to ES6 style promises and convert any JQuery promises that are being passed around to ES6 promises before use by calling Promise.resolve( jqPromise)
Write the equivalent of Promise.resolve in reverse to convert an ES6 promise into a JQuery promise. I would rate this as possible but a huge hack backwards in the wrong direction.

Is promise constructor function necessary or can it be avoided?

According to Promise - Javascript | MDN,
The constructor is primarily used to wrap functions that do not
already support promises.
At a low level, the functions that already support promises would
be doing this right i.e constructing a promise using Promise and returning it back?
Is there a better way to create a promise other than using the Promise constructor function?
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves? In other words, we have to wrap it like this somewhere in the library correct?
At the lowest level? Yes, probably.
Depends on the context. If the value you want to resolve the value to is already available, then you'd use Promise.resolve(theValue). If you want to wait for multiple promises you'd use Promise.all(allThePromises). And of course every call to .then returns a new promise.
If you want to do anything with the value of a promise, then yes, you have to pass a callback to .then. There is no other way to get the value.
Having said all that, ES2017 introduced async functions which are basically syntactic sugar for promises. async functions always return a promise and you can use await to unwrap promises. Example:
async function get() {
return await Promise.resolve(42);
}
get().then(console.log);
At a low level, the functions that already support promises would be doing this right i.e constructing a promise using Promise and returning it back?
The eventual goal is that even the low-level APIs within Node.JS will be using the Promise syntax so there will be no need for callbacks. The PromiseJS community considers the constructor syntax to be a polyfill for this eventual behavior. Source.
In practice, this is obviously not the case. Browsers, Node.JS and other Javascript runtime environments make heavy use of callbacks, and so the Promise constructor is used.
Is there a better way to create a promise other than using the Promise constructor function?
Yes- but this depends on application.
Most obviously, if you are using an API which already returns a promise, you can use .then() and .catch() syntax to chain promises together.
There are also a number of libraries which extend the default Promise functionality and provide convenience methods for increased performance and readability. For instance, Bluebird (a common PromiseJS library) offers a way to evaluate the result of multiple promises created concurrently for faster overall runtime.
You can also construct Promises from other paradigms which simplify code- for instance Promise.Promisify which converts a callback function into a Promise one, or Observable.toPromise which converts Observables to promises.
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves? In other words, we have to wrap it like this somewhere in the library correct?
Similar to the answer to your first question, this is a symptom of code currently using the callback paradigm. If all libraries used Promises on a lower level, this wouldn't be the case.
At a low level, the functions that already support promises would be doing this right i.e constructing a promise using Promise and returning it back?
Yes. Maybe. At a low level, we don't know how functions that already support promises do construct those. Imagine what the Promise constructor itself uses to construct promises…
Is there a better way to create a promise other than using the Promise constructor function?
No, there's no other way accessible to JS. But as MDN notes, you should rarely ever need to do this yourself, and rather just use other functions that already create promises for you (which by themselves of course go through the Promise constructor somehow).
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves?
Not necessarily. At a low level, you could also register any arbitrary data structure that allows to resolve a promise, this does not necessarily need to be a callback function. (It is however indeed equivalent in power to registering the resolve callback function).
For example the native implementation of the fetch API (afaik the first native API that directly returns promises) will hardly create JS callback functions anywhere to resolve its promises.

How long a Promise can remain in pending state?

I'm using Promises in Angular (4) project and I have a question about them that I couldn't find a response to it in the docs.
When I create a Promise, I basically wait for an async answer from a service/party. But how long should I expect this Promise to stay in pending state?
Is there any mechanism that will terminate it after a while?
How reliable is this concept of waiting/pending?
Let's suppose that I need to get some data from a busy service that can answer even after few minutes of waiting, maybe more, no matter if the computing of the response is a resource intensive process or that service is linked with another one that is responding very slow.
Is there anything on the client side that will somehow terminate my Promise and determine/force to create another one to ask again for my data?
Someone suggested to upgrade to Observables, and I will do that, but for now I want to keep using Promises, at least for some areas of the code.
Tks a lot
A Promise can be in pending state as long as the page is loaded.
You can wrap the call in another Promise where you introduce a timeout like shown in
let wrappingPromise = new Promise((resolve, reject) => {
var error = false;
setTimeout(function(){
reject("some error");
}, 3000);
this.http.get(...).toPromise().then(res => {
if(!error) {
resolve(res.json);
}
});
});
This will cause an error when the timeout is reached.
It will still wait to receive the full response.
An Observable might be able to forward a cancellation and close the connection, so that the result isn't even received anymore when the timeout is reached. This might depend on whether the concrete implementation and the browser used browser API supports that.
new Promise(() => {}) will never settle, like a callback never called.
A promise is a return object you attach callbacks to, instead of passing callbacks into the function. That's all. It is not a control surface of the asynchronous operation that was just started.
Instead, look to the asynchronous API you called for such controls, if it has them.
Creating promises
Most people are consumers of promises returned from asynchronous APIs. There's no reason to create a Promise other than to wrap a legacy callback API. In an ideal world there'd be no need.

When would someone need to create a deferred?

It seems generally that creating deferred objects is now commonly discouraged in favor of using the ES6-style Promise constructor. Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?
For example, on this page, the following example is given as justification for using a deferred:
function delay(ms) {
var deferred = Promise.pending();
setTimeout(function(){
deferred.resolve();
}, ms);
return deferred.promise;
}
However, this could be done just as well with the Promise constructor:
function delay(ms) {
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve();
}, ms);
});
}
Does there exist a situation where it would be necessary (or just
better somehow) to use a deferred?
There is no such situation where a deferred is necessary. "Better" is a matter of opinion so I won't address that here.
There's a reason that the ES6 promise specification does not have a deferred object. You simply don't need one. Anything that people used to use a deferred object for can always be done another way that doesn't use a deferred object.
First off, the majority of uses fit very nicely into the promise constructor model. Secondly, any other cases that didn't fit quite so cleanly into that model can still be accomplished with the promise constructor or by starting with a resolved promise and chaining to it.
The main use case I've seen for a deferred is when you want to pass the ability to resolve() or reject() off to some other piece of code other than the code that created the promise. A Deferred made that very easy since you could just pass the deferred object and it had public methods for resolving or rejecting it. But, with a promise, you can also just pass the resolve and/or reject methods. Since they are bound to the specific object automatically, you can just pass the function references. And, in other cases, you can just let the other code create their own promise and resolve/reject it themselves and have that operation linked to yours rather than letting them resolve/reject your promise. Is all that quite as clean as passing a deferred object? Mostly a matter of opinion, but neither are very common use cases and all are something that can be accomplished without a separate deferred object.
And, as torazaburo points out, letting some external code resolve or reject your promise is a bit of an anti-pattern in its own right. You created the promise - you resolve/reject it. If you want to use external events to decide when to resolve/reject it, then have them notify you (via their own promise or callback) and you can resolve/reject your own promise. Or, have them create their own promise that you can use. That's really the desired model. Or, let them chain onto your promise so that the end result is gated by when their operation is done.
If one was used to coding with the deferred object (say with a jQuery deferred), it might take a little getting used to coding without it, but after a little while you just start to think differently and it starts to come natural to just use the promise constructor.
Once you promisify the sphere of async operations that you use in any given application, it's pretty rare that you ever even need to create your own promises any more because you are mostly just building off promises that the async functions you call are already creating or using flow control operations like Promise.all() which create uber promises for you.
This is the main point of anti-patterns. Use the promises that are already created for you rather than manually create more. Chain them. Return promises from .then() handlers to link async operations under logic control.
Of course, there are existing async operations that don't return promises for which somebody needs to create a promise, but that should be done in a promisify layer somewhere outside the purvey of your main coding logic and done only once for that operation and then code that calls the async operation should be able to just use the returned promises.
Native Promises don't have all the built-in methods that deferred has out of the box, for example the method to resolve the promise outside the scope of its constructor (very easy to implement with native Promise, though), and the ability to look at the status of a promise (which is hidden from regular JavaScript on native Promises, though it can be inspected in the dev tools).
The main reason to use deferred today would be backwards compatibility with code that depends on those extra methods. Hard to give a definitive answer to your question without stepping onto opinion territory.

Categories