I am using Rxjs Observables to handle nested ajax request like the following way:
Rx.Observable.fromPromise($.getJSON('list1.json'))
.switchMap(function responseA(aResponse){
/* processing aResponse*/
if(aResponse.fileName){
return Rx.Observable.fromPromise($.getJSON(aResponse.fileName));
}
return Rx.Observable.fromPromise($.getJSON('list2.json'));
})
.subscribe(function(finalResponse){
/* processing finalResponse */
});
But, as you know, it can also be done without using Observables and with only promises:
$.getJSON('list1.json')
.then(function responseA(aResponse){
/* processing aResponse*/
if(aResponse.fileName){
return $.getJSON(aResponse.fileName);
}
return $.getJSON('list2.json');
})
.then(function(finalResponse){
/* processing finalResponse */
});
Both code works, but it seems to me that it is more clean in terms of code to use promises.
Am I missing something here as I've heart that Rx Observable is more standard and efficient to handle asynchronous requests.
Which one (promise or Observable) will be the best in terms of code organization, convention and performances to handle ajax request ?
If I prefer to use Observable then which operators (switchMap/MergeMap) will be preferable in these kind of situation ?
Am I missing something here as I've heart that Rx Observable is more standard and efficient to handle asynchronous requests.
No, you're not missing anything. Rx is really useful but in that particular case promise based code is simpler.
In general, if you need a singular value - prefer a promise. If you need multiple values in/out - use observables (or the further ahead in spec async iterators).
Rx would be nice if you want to quickly need to add:
Retrying the requests if they failed (with Observable.defer).
Only caring about the last request.
If you need built in cancellation.
It's worth mentioning - promises can do all that if you use a library. It's not a fundamental property of observables.
Rx really shines if your input is more than a single call. If you needed to make these calls whenever the user clicks something, ignore clicks on some condition, debounce it to 100ms and then only care about the last call - Rx would be really useful.
In this particular case - promises are simpler and fine. Your promise code can be simplified further:
$.getJSON('list1.json').then(x => $.getJSON(x.fileName || 'list2.json'))
There are couple of really good articles out there in web, here is couple of them, I hope those will help you to understand the difference properly.
What Promises Do That Observables Can’t
https://egghead.io/lessons/rxjs-rxjs-observables-vs-promises
Related
How does one decide between promises, async awaits, and mapping operators like concatMap?
Here's my specific case, but I'm also curious about how you decide in general:
I am making an http call to my backend, and then I make another http call afterwards. When processing the json data from the second call, I need to use values that are returned by the first call. In this situation, is it better to use async await, a promise or concatMap? Also in general, what are the guidelines for deciding which to use?
Here is what I current have, using concatMap. (I am dynamically generating child components from my getTask http call, and each child component needs to have access to annotationFormats).
this.dashboardService.getAnnotationFormats()
.pipe(
concatMap(annotationFormats=> this.dashboardService.getTasks())
)
.subscribe(
(tasks)=>{
for(let task of tasks){
const componentFactory=this.CFR.resolveComponentFactory(DashboardItemComponent);
const componentRef=this.vc.createComponent(componentFactory);
componentRef.instance.task=task;
componentRef.instance.annotationFormats=annotationFormats;
componentRef.instance.compInteraction=this;
this.taskRef.push(componentRef);
}
}
);
Async/await and promises are basically the same with different syntax. Asynchronous code that will run once after some job has been finished.
As a rule, I would never never use none of those while using Angular. Angular comes with RxJS out of the box, which is so much more than promises. You can use RxJS for running async code once when a job has completed, but it also gives you the possibility of creating streams of data and manipulating them in so many different ways.
It does take a bit to fully understand RxJS and reactive programming but once you do you realize how much you can do with it.
In your case, I like to use the operator forkJoin, since the two requests seem independent from each other. You can give it a list of resources you want to obtain and will execute the async code in subscribe once they have all completed, which makes it perfect for http requests:
forkJoin({
annotationFormats: this.dashboardService.getAnnotationFormats(),
tasks: this.dashboardService.getTasks(),
})
.subscribe(
({tasks, annotationFormats})=>{
for(let task of tasks){
const componentFactory=this.CFR.resolveComponentFactory(DashboardItemComponent);
const componentRef=this.vc.createComponent(componentFactory);
componentRef.instance.task=task;
componentRef.instance.annotationFormats=annotationFormats;
componentRef.instance.compInteraction=this;
this.taskRef.push(componentRef);
}
}
);
Take your time to learn RxJS, I guarantee it will pay off. Whenever you are using RxJS and it feels too complex or wrong, that is because it probably is. Head to the RxJS documentation and look for something that might useful, and if you don't find anything a quick google search will probably get you the solution anyways. Point is, don't just use it blindly, always try to understand how it works.
I hope this is useful. :)
Edit:
For RxJS < 6.5, the syntax is a bit different:
forkJoin(
this.dashboardService.getTasks(),
this.dashboardService.getAnnotationFormats()
)
.subscribe(
([tasks, annotationFormats])=>{
for(let task of tasks){
const componentFactory=this.CFR.resolveComponentFactory(DashboardItemComponent);
const componentRef=this.vc.createComponent(componentFactory);
componentRef.instance.task=task;
componentRef.instance.annotationFormats=annotationFormats;
componentRef.instance.compInteraction=this;
this.taskRef.push(componentRef);
}
}
);
Notice we pass the resources as arguments, not as an object, and the result in the subscribe will be in an array form instead of an object too.
They have different use. async/await is used when you want to hold on a place where you have written some asynchronous code. while primises are tool to spot a place where async code is executed and invokes callback.
Use case: Call a function every minute (60000 ms) that dispatches store action to fetch lastUpdated status of items, which upon response and filtering, updates the store, and updated store is read as an observable and displayed in the view). This needs to happen for as long as the web app is open (so indefinitely).
Currently, I'm using this:
this.refreshDate = window.setInterval(
() => this.store.dispatch(new FetchLastUpdate())
, 60000);
And when view is destroyed/dismounted, I delete the interval as so:
if (this.refreshDate) {
clearInterval(this.refreshDate);
}
Is this efficient/effective, or is it troublesome?
Why would I want to use an RxJS polling strategy like:
interval(60000)
.pipe(
startWith(0),
switchMap(() => this.store.dispatch(new FetchLastUpdate()))
);
Or
timer(0, 60000)
.pipe(
switchMap(() => this.store.dispatch(new FetchLastUpdate()))
);
TL;DR: window.setInterval() vs. RxJS timer()/interval()
Conclusion/answers (for ease of research):
There is great benefit to using RxJS functions to set an interval or perform polling, these benefits are explained in the selected answer but also in comments, but it is concluded (by discussions in the comments) that for the very simple requirement defined in the "Use case" section at the beginning of this post, it is unnecessary to use RxJS, and in fact if you are not using RxJS in any other part of your program, do not import it just for this, however in my case, I had already imported and used RxJS elsewhere.
Advantage of RxJS:
Laziness
You can create your Observables and until you call subscribe nothing is happening. Observable = pure function. This gives you more control, easier reasoning and allows for next point...
Composability
You can combine interval/timer with other operators creating custom logic very easily in unified way - for example you can map, repeat, retry, take... etc. see all operators
Error Handling
In case of an error you are responsible for calling clearTimeout/clearInterval - Observables are handling this for you. Resulting in cleaner code and fewer memory leak bugs.
Of course anything you do with Observables you can also do without Observables - but that's not the point. Observables are here to make your life easier.
Also note that interval/timer are not good observable factories for polling because they do not "wait" for your async action to finish (you can end up with multiple async calls running over each other). For that I tend to use defer and repeatWhen like this:
defer(() => doAsyncAction())
.pipe(
repeatWhen(notifications => notifications.pipe(delay(1234)))
);
window.setInterval doesn't care about your callbacks state, it'll execute at the given interval despite the status of the execution of the past callback, and the only way to make it stop and skip is clear the interval or reinitialize it.
On the other hand, RxJS Observable based solutions(interval, timer) allow you to pipe conditional operators (takeWhile, skipWhile for example) which allows you to add a stop or implement a stop-start logic by just flipping a boolean flag, instead of adding complicated logic of clearing the interval, and then recreating it.
And they are observables, you can listen to them all across the application, and attach any number of listeners to it.
Error Handling is better too, you subscribe to all successes, and handle everything in a catch callback.
I decided to have a fallback call to the server when creating a model in case we can't find a value from the information available locally. I want to have it async if possible, does it mean I have to make everything in this chain of code consume and return promises?
I'm going to use pseudo code to illustrate this point initially, as the call stack can be a little long and so we don't include things that aren't central to this question. Let me know if you need more to go on though.
function router() {
if (condition) {
controller.renderDocument(options);
}
}
controller.renderDocument(options) {
documentCollection.findOrCreateDocumentHolder(options);
}
documentCollection.findOrCreateDocumentHolder(options) {
var model = this.findOrCreateDocument(options);
}
documentCollection.otherFunction(options) {
// just to illustrate that there's several entry points to this kind of functionality
var model = this.findOrCreateDocument(options);
}
documentCollection.findOrCreateDocument(options) {
if (!options.type)
options.type = resolveType(options);
// other things that use the found options.type
return model;
}
resolveType(options) {
var locallyResolved = resolveLocally(options);
if (locallyResolved)
return locallyResolved;
// try the server as a fallback
var serverResolved = resolveFromServer(options.id);
return serverResolved;
}
resolveLocally(options) {
return stuff;
}
resolveFromServer(id) {
return ajaxRequestResult();
}
Obviously the actual code is a bit longer and actually does stuff.
It feels excessive to make all of this use chaining promises for the sake of 1 possible ajax request down the pipe, especially as this will be a rare occurrence. The other alternative is to just make a synchronous AJAX request.
Are my only options to make everything use promises and whens, or to make it a synchronous AJAX request? Is there a nicer alternative? I'm thinking of C#'s await keyword, but I'm sure other languages have similar functionality.
I want to have it async if possible, does it mean I have to make everything in this chain of code consume and return promises?
Yes. Something that is potentially asynchronous must always return a promise, and must always be consumed as if it was asynchronous (promises enforce this anyway).
Is the only other alternative to just make a synchronous AJAX request?
Yes, and you really don't want that.
Is there a nicer alternative? I'm thinking of C#'s await keyword, but I'm sure other languages have similar functionality.
In fact, async-await is coming to ECMAScript as well. But it doesn't make anything synchronous, it rather is just syntactic sugar for promises-everywhere.
Once you start with promises they do spread around, no way around it really since once you go async you must either wait (not feasible) or pass callbacks (which promises solve).
My approach is to embrace them, you'll be more often returning promises then immediate values, but you'll always take care of handling success/error and have a consistent way of dealing with data flow.
There are many more sources of asynchronicity than AJAX requests and I really can't think of a case where I would require a synchronous return value in Javascript.
I have a function,
Edit1 - Updated function with real one because the previous one was simplified synchronous function and the code would have worked as correctly pointed by #AlexMA in the comments
'returnSuccessOrFailure': function () {
return driver.findElement(wd.By.css('div#button')).then(function (button) {
return button.getAttribute('class').then(function (status) {
return status;
});
});
}
In my node.js test, my assertion is failing because the assert is called before returnSuccessOrFailure finishes execution.
var value = returnSuccessOrFailure();
assert.equal(value,'success', 'Looks like something failed');
If I implement a promise in returnSuccessOrFailure and chain my assert then that works. My question is do I have to implement promises all the time for such situations to block the execution? I am new to Javascript and the async nature of it and any insight when to use promises and when not to would be useful.
you don't have to "implement a promise" in, just return the one you already have:
returnSuccessOrFailure': function () {
return driver.findElement(wd.By.css('div#button')).then(function (button) {
...
but then, yes, you do still need to put your assert in a done handler
returnSuccessOrFailure().done(function(value) {
assert.equal(value,'success', 'Looks like something failed');
}
Chaining you asserts will not only make it work but will also make for more readable code. Knowing what happens in what order can be useful when going back to refactor. Not only that but the structure of callbacks/promises also allow for easily written timer tests.
Also, since your test needs to have the current state of execution, it is more than likely that writing tests with asserts in callbacks is what you will need anyway.
My question is do I have to implement promises all the time for such situations to block the execution?
Notice that promises don't block the execution. They defer the execution of code that depends on the result, notice that you're still chaining callbacks on them.
I am new to Javascript and the async nature of it and any insight when to use promises and when not to would be useful.
Promises are useful wherever you have some code that might run asynchronously and needs to pass back an asynchronous result. Otherwise you would need to use callbacks, which are way more ugly than promises.
This is part of code contracts and representing preconditions (what holds before you execute), postconditions (what holds after you execute), and object invariants (what can not change). JavaScript does not have native support for this, but you can use third party libraries (Cerny.js, ecmaDebug, jsContract, or jscategory)
I think it depends on your coding style, is it EAFP(Easier to ask for forgiveness than permission) or LBYL(Look before you leap). Both are viable! In most compiled languages you would use LBYL. However in Python for example you would use EAFP.
Generally if you know you will fail you want to fail fast. If you like to use assertions to ensure code fails fast it is up to you.
I'm not so experienced/elegant programmer. I hope my question is understandable.
I have used java/c++ for most part of my life so my mind is object oriented. Then I learned python and I enjoyed very much functional mind. Now I'm approaching js. It is challenging because it is function based (and I liked it a lot), functional (with underscore I have a lot of pythonic iterutils methods) and asynchronous (it hurts).
A lot of time I have some back-end sync procedural flow like:
if exist(user):
foo(user)
# ok
else:
add(user)
# user added
Now I have to handle this with the so called callback hell:
exists(user, function(userExist) {
if( userExist ) {
foo( user, function(fooResult) {
/* ok */
});
} else {
add( user, function(addResult) {
/* user added */
});
}
});
Sometimes the controls are more nested: check for token, if token is valid check for user exists, if user exists check for valid parameters, then check for no error in foo on user, etc…
Those controls are simply synchronous and imperative-like. Nothing else to say. While with sync language like python I can handle this is (not elegant but at least) readable code with the use of small function that returns values , with javascript I don't know how to refactor things in readable small function. All functions I wrote does not have any return statements but just callback(something_weird_defined_in_caller_function) and I lost myself.
I don't think that promises are good on my case because are more for piping events, IIUC. So I'm looking for some pattern using async library to handle this case:
- continue to execute functions in series only if the previous one succeeded.
Please any help will be appreciated.
I don't think that promises are good on my case because are more for piping events, IIUC
No. Promises don't represent a stream of events to pipe, but a single result that will arrive later (asynchronously). This is exactly what they were made for, and they will give you imperative-like looking code (instead of a nesting callback hell).
Admittedly, you still need nesting for control structures. The code that you presented won't look much different except for the callbacks going into .then() calls, and promises being returned.
However, you can also use exceptions for control flow. Instead of using exists that returns a Promise<boolean>, you could use a find function that returns a Promise<User> which would get rejected when the user doesn't exist. It could be used like
find(user).then(function(/*user*/) {
return foo(user) /* .then(function(fooResult) {
…
}); */
}).catch(UserNotFoundError, function(e) {
return add(user) /* .then(function(addResult) {
…
}); */
});
Which of those to choose is debatable, rejections should be exceptional.