Accomplish Promise Chaining - javascript

Background
I have a nodejs server running and I installed the promise package which follows the promise api specs.
Since I succeeded in making denodeify(fn, length) work, I am now in the process of chaining promises, but I am failing to grasp the main concepts.
What I tried
By reading the documentation example on the specification page, I reached the following code:
let Promise = require("promise");
let write = Promise.denodeify(jsonfile.writeFile);
let read = Promise.denodeify(jsonfile.readFile);
read("dataFile.txt").then( () => {
write("./testFile.txt", "hello_World", TABS_FORMATTING).then(console.log("file complete"));
});
Which is quite different from the examples I see, for example, in the Solutions Optimist tutorial:
loadDeparture( user )
.then( loadFlight )
.then( loadForecast );
Objective
My objective is to make my code as beautiful as the example I showed before, but I don't understand how I can make as concise as it is right now.
Question
1 - What changes do I need to perform in my code to achieve that level?

The given example uses named function to make it look as good as it can get, but that can be a bit redundant because then you're creating functions for every little thing in the chain. You must pick and choose when to use named functions over anonymous functions.
One thing you must also realize is that to chain promises you must return them.
So to make it a proper chain you must return the write method so it is passed down to the next step.
Also make sure that the catch() method is used at the bottom of every promise chain so that errors aren't silently swallowed.
Note that in the example here I'm using the ES2015 arrow functions to return the write() method as that makes it looks better(which seemed to be the purpose of your question).
let Promise = require("promise");
let write = Promise.denodeify(jsonfile.writeFile);
let read = Promise.denodeify(jsonfile.readFile);
read("dataFile.txt")
.then(() => write("./testFile.txt", "hello_World", TABS_FORMATTING))
.then(results => console.log("file complete", results))
.catch(error => console.error(err));
I'd recommend reading this article for some best practices.

Nesting promises kind of defeats the purpose because it creates pyramid code (just like callbacks).
The main concept that may be escaping you is that you can return inside a then and the returned value (can be a promise or a value) can then be accessed in a chained then:
read("dataFile.txt").then( () => {
return write("./testFile.txt", "hello_World", TABS_FORMATTING);
}).then( () => {
console.log("file complete");
});
Now, you can extract the functions:
function writeTheFile() {
return write("./testFile.txt", "hello_World", TABS_FORMATTING);
}
function consoleLog() {
console.log("file complete");
}
read("dataFile.txt")
.then(writeTheFile)
.then(consoleLog);

Related

Is the return type using .then different from without it?

My code works with the following:
export async function FetchAPI(props){
const url = `www.website.com/${props}`
let res = await fetch(url)
let response = await res.json()
return response
}
But when I try to clean up the code using better practices, I get error for the below code saying it is returning undefined.
export async function FetchAPI(props){
const url = `www.website.com/${props}`
fetch(url)
.then((resp => {
resp.json()
return resp
}))
}
Anyone understand the differences and how I can get the second one to work?
The correct code for the .then() version is this:
export function FetchAPI(props){
const url = `http://www.website.com/${props}`;
return fetch(url).then(resp => {
return resp.json();
});
}
Is the return type using .then different from without it?
This fixed version would generate the same exact returned results as your await version with the same URL. Both would return a promise that would resolve/reject based on the results of the fetch and the JSON conversion of the body.
Note: URLs used in Javascript programming should contain the protocol as shown here.
I wonder why using thenable rather than async/await is better practice.
Async/await is a more modern syntax. When sequencing multiple asynchronous operations or branching based on asynchronous results, it is pretty much always simpler to write, read and debug with async/await than using .then().
When you just have a single asynchronous operation, you can sometimes just return that promise and using async/await doesn't necessarily provide any advantages. It's entirely up to the designer of the code which one to use - either can work just fine when written properly.
There are times when a simple .catch() is cleaner than putting a try/catch around the whole block too for localized error handling. Like many things with coding style, there's no absolute right and wrong, just opinions on what looks like the cleanest code.
Also, if you want your code to run in older Javascript environments that don't support async/await, then you may need to use .then() and .catch() or transpile your code to an older target.
For a related discussion see Async / await vs then which is the best for performance?.

Loop through AWS Lambda Nodejs SDK function

I'm new to Nodejs and having trouble understand this issue: I tried to run a describe function against an array, and the AWS function seems to run after the main function has finished.
Here's the main function: (loop thru a list of ACM ARNs and check the status)
var checkCertStatus = function(resolveObj){
var promise = new Promise(function(resolve, reject){
console.log('1');
var retObj='';
resolveObj.Items.forEach(function(element) {
var certDescribeParams = {
CertificateArn: element.sslCertId
};
console.log('2');
acm.describeCertificate(certDescribeParams, function(err, data) {
if(err) reject(new Error(err));
else {
console.log(data.Certificate.DomainName + ': ' + data.Certificate.Status);
retObj+=data;
}
});
});
console.log('3');
resolve(retObj);
return promise;
})
}
Based on the debug log, assuming there are 2 items need to be processed, what I got:
1
2
2
3
example.com: ISSUED
example2.com: ISSUED
Basically, I need to pass this result to the next function in the chain (with promise and stuff).
Welcome to Node.js! Speaking generally, it might be helpful to study up on the asynchronous programming style. In particular, you seem to be mixing Promises and callbacks, which may make this example more confusing than it needs to be. I suggest using the AWS SDK's built-in feature to convert responses to Promises.
The first thing I notice is that you are manually constructing a Promise with a resolve/reject function. This is often a red flag unless you are creating a library. Most other libraries support Promises which you can simply use and chain. (This includes AWS SDK, as mentioned above.)
The second thing I notice is that your checkCertStatus function does not return anything. It creates a Promise but does not return it at the end. Your return promise; line is actually inside the callback function used to create the Promise.
Personally, when working with Promises, I prefer to use the Bluebird library. It provides more fully-featured Promises than native, including methods such as map. Conveniently, the AWS SDK can be configured to work with an alternative Promise constructor via AWS.config.setPromisesDependency() as documented here.
To simplify your logic, you might try something along these lines (untested code):
const Promise = require('bluebird');
AWS.config.setPromisesDependency(Promise);
const checkCertStatus = (resolveObj) => {
const items = resolveObj.Items;
console.log(`Mapping ${items.length} item(s)`);
return Promise.resolve(items)
.map((item) => {
const certDescribeParams = {
CertificateArn: item.sslCertId,
};
console.log(`Calling describeCertificate for ${item.sslCertId}`);
return acm.describeCertificate(certDescribeParams)
.promise()
.then((data) => {
console.log(`${data.Certificate.DomainName}: ${data.Certificate.Status}`);
return data;
});
});
};
We're defining checkCertStatus as a function which takes in resolveObj and returns a Promise chain starting from resolveObj.Items. (I apologize if you are not yet familiar with Arrow Functions.) The first and only step in this chain is to map the items array to a new array of Promises returned from the acm.describeCertificate method. If any one of these individual Promises fails, the top-level Promise chain will reject as well. Otherwise, the top-level Promise chain will resolve to an array of the results. (Note that I included an inessential .then step just to log the individual results, but you could remove that clause entirely.)
Hope this helps, and I apologize if I left any mistakes in the code.

removing promise dependencies

I'm aware of the power of promises, however I have several old functions that are synchronous:
function getSomething() {
return someExternalLibrary.functionReturnsAValue()
}
console.log(getSomething()); // eg prints 'foo'
Unfortunately, when someExternalLibrary updated, it has removed functionReturnsAValue() and has lumped me with functionReturnsAPromise():
function getSomething() {
return someExternalLibrary.functionReturnsAPromise()
}
console.log(getSomething()); // now prints '[object]'
This of course, breaks absolutely everything written that depends on what used to be a simple value.
Obviously, I'd prefer two things:
ask the original library to keep a synchronous return value. (Not going to happen -- b/c they have refused)
A way to actually wait for a value
I have read numerous articles on why promises are great, ad nauseam, but the simple fact is: If I embrace promises, all I really do is shuffle promises onto some other part of the code, which then must deal with the promise of a value...
Is there a way (in nodejs) to actually wait for a promise to get itself together?
The best I can find is to use coroutines and yield, but really, it's still passing the buck. To be clear, I want the function getSomething to continue to return a value. Is there a way to do it?
Clearly, I fear I've misunderstood something about Promises...
The app is for non-browser implementations and runs purely from the command line. I've been trying to understand how bluebird's reflect() might help, to no avail.
(Yes, I'm aware this question has been asked many times in various formats, but I can't find a suitable answer to the core issue. If anything, I'm looking for the opposite of this question. The closest related (but unhelpful) question I can find is: Managing promise dependencies.)
There's the concept of generator functions. These are a special kind of function in both syntax (asterisk notation) and semantics. Unlike regular functions, generator functions return something that's also new to ECMAScript: iterators. Iterators happen to be objects made specifically to be iterated on, e.g. with the all new for...of loop. They can be also iterated on manually by calling their 'next' method. Each such call produces an object containing two properties: 'value' (iterator's current value) and 'done' (a boolean indicating whether we reached the last value of the iterable). However, the best thing about generator functions is their ability to suspend their execution each time a keyword 'yield' is encountered. Let's have a glimpse of how it all works together:
'use strict';
let asyncTask = () =>
new Promise((resolve, reject) => {
if (Math.random() > 0.5) {
resolve(1);
} else {
reject(new Error('Something went wrong'));
}
});
let makeMeLookSync = fn => {
let iterator = fn();
let loop = result => {
!result.done && result.value.then(
res => loop(iterator.next(res)),
err => loop(iterator.throw(err))
);
};
loop(iterator.next());
};
makeMeLookSync(function* () {
try {
let result = yield asyncTask();
console.log(result);
} catch (err) {
console.log(err.message);
}
});
The short answer
I am told repeatedly: You can't undo functions that have been promisified.
Edit: An upcoming solution
It appears that the ES2017 (although still draft), goes a long way in making promisified code easier to work with:
https://ponyfoo.com/articles/understanding-javascript-async-await
It seems that there is also a node library ready for this support too: https://github.com/normalize/mz.
Using this methodology, having apis converted to Promises won't be so bad (although it still appears that promises still poison the rest of the codebase):
const fs = require('mz/fs')
async function doSomething () {
if (await fs.exists(__filename)) // do something
}
The rest of this answer is just a general commentary on the problem.
Why we need a solution
Let's start with a sample piece of traditional synchronous code, in 3 flavours from more 'older-fashioned' to 'newer':
This is the traditional javascript way, requiring exception based programming to handle unexpected errors:
function getSomething() {
if (someproblem) throw new Error('There is a problem');
return 'foo';
}
However, adding try/ catch statements becomes very laborious and tedious, very quickly.
With the advent of node.js, callbacks were made popular, which nicely circumvented the issue, since each caller was explicitly forced to deal with error conditions in the same callback. This meant less errors in the caller's code:
function getSomething(callback) {
if (callback) {
if (someproblem)
callback(new Error('There is a problem'), null);
else
callback(null, 'foo');
}
return 'foo';
}
Then, the after some teething issues, node.js quickly proved itself for server-side communications, and people were amazed at the speed that asynchronous solutions provided. Node application frameworks like Express and Meteor grew, which focused on this.
Unfortunately, using the same callback scheme quickly became troublesome and the developers dealing in asynchronous code started using Promises in an effort to linearize the code, to make it readable, like the traditional (try/catch) code was.
The problem is that it got evangenlized too much. Everyone started thinking that Promises are the way to go. Personally, I call it a poison on a codebase. Once you have anything that uses Promises, your whole codebase must become asynchronous. This is not always a sensible nor a practical solution, IMHO.
The worst of all side effects is that the above function, even though it is completely synchronous, can be written in Promises too:
var bluebird = require('bluebird');
function getSomething() {
// IMHO, this is ridiculous code, but is increasingly popular.
if (someproblem) return Promise.reject(new Error('There is a problem'));
return Promise.resolve('foo');
}
For those who doubt this is a problem, perhaps should look at the SO question: How do I convert an existing callback API to promises?. Pay particular attention to #3, Node-style callback.
So, for anyone who cares, I would like to suggest that there needs to be a 'pill' for Promises. I urge that we need more than promises: we need results, and sometimes in a timely manner.
Take a look at the default node.js api. It does not use Promises. It also provides both synchronous and asynchronous calls to appropriate parts of the api (eg File System).
For those of you who feel tempted to downvote this answer: that is your prerogative, but there are clear issues on when Promises are not the answer, and I feel strongly that there are cases when we need to be able to re-synchronize decoupled code.
I also apologize for this 'blog-post' styled answer.

Improving on the callback structure [duplicate]

Can someone give a clear definition together with a simple example that explains what is a "callback hell" for someone who does not know JavaScript and node.js ?
When (in what kind of settings) does the "callback hell problem" occur?
Why does it occur?
Is "callback hell" always related to asynchronous computations?
Or can "callback hell" occur also in a single threaded application?
I took the Reactive Course at Coursera and Erik Meijer said in one of his lectures that RX solves the problem of "callback hell". I asked what is a "callback hell" on the Coursera forum but I got no clear answer.
After explaining "callback hell" on a simple example, could you also show how RX solves the "callback hell problem" on that simple example?
1) What is a "callback hell" for someone who does not know javascript and node.js ?
This other question has some examples of Javascript callback hell: How to avoid long nesting of asynchronous functions in Node.js
The problem in Javascript is that the only way to "freeze" a computation and have the "rest of it" execute latter (asynchronously) is to put "the rest of it" inside a callback.
For example, say I want to run code that looks like this:
x = getData();
y = getMoreData(x);
z = getMoreData(y);
...
What happens if now I want to make the getData functions asynchronous, meaning that I get a chance to run some other code while I am waiting for them to return their values? In Javascript, the only way would be to rewrite everything that touches an async computation using continuation passing style:
getData(function(x){
getMoreData(x, function(y){
getMoreData(y, function(z){
...
});
});
});
I don't think I need to convince anyone that this version is uglier than the previous one. :-)
2) When (in what kind of settings) does the "callback hell problem" occur?
When you have lots of callback functions in your code! It gets harder to work with them the more of them you have in your code and it gets particularly bad when you need to do loops, try-catch blocks and things like that.
For example, as far as I know, in JavaScript the only way to execute a series of asynchronous functions where one is run after the previous returns is using a recursive function. You can't use a for loop.
// we would like to write the following
for(var i=0; i<10; i++){
doSomething(i);
}
blah();
Instead, we might need to end up writing:
function loop(i, onDone){
if(i >= 10){
onDone()
}else{
doSomething(i, function(){
loop(i+1, onDone);
});
}
}
loop(0, function(){
blah();
});
//ugh!
The number of questions we get here on StackOverflow asking how to do this kind of thing is a testament to how confusing it is :)
3) Why does it occur ?
It occurs because in JavaScript the only way to delay a computation so that it runs after the asynchronous call returns is to put the delayed code inside a callback function. You cannot delay code that was written in traditional synchronous style so you end up with nested callbacks everywhere.
4) Or can "callback hell" occur also in a single threaded application?
Asynchronous programming has to do with concurrency while a single-thread has to do with parallelism. The two concepts are actually not the same thing.
You can still have concurrent code in a single threaded context. In fact, JavaScript, the queen of callback hell, is single threaded.
What is the difference between concurrency and parallelism?
5) could you please also show how RX solves the "callback hell problem" on that simple example.
I don't know anything about RX in particular, but usually this problem gets solved by adding native support for asynchronous computation in the programming language. The implementations can vary and include: async, generators, coroutines, and callcc.
In Python we can implement that previous loop example with something along the lines of:
def myLoop():
for i in range(10):
doSomething(i)
yield
myGen = myLoop()
This is not the full code but the idea is that the "yield" pauses our for loop until someone calls myGen.next(). The important thing is that we could still write the code using a for loop, without needing to turn out logic "inside out" like we had to do in that recursive loop function.
To address the question of how Rx solves callback hell:
First let's describe callback hell again.
Imagine a case were we must do http to get three resources - person, planet and galaxy. Our objective is to find the galaxy the person lives in. First we must get the person, then the planet, then the galaxy. That's three callbacks for three asynchronous operations.
getPerson(person => {
getPlanet(person, (planet) => {
getGalaxy(planet, (galaxy) => {
console.log(galaxy);
});
});
});
Each callback is nested. Each inner callback is dependent on its parent. This leads to the "pyramid of doom" style of callback hell. The code looks like a > sign.
To solve this in RxJs you could do something like so:
getPerson()
.map(person => getPlanet(person))
.map(planet => getGalaxy(planet))
.mergeAll()
.subscribe(galaxy => console.log(galaxy));
With the mergeMap AKA flatMap operator you could make it more succinct:
getPerson()
.mergeMap(person => getPlanet(person))
.mergeMap(planet => getGalaxy(planet))
.subscribe(galaxy => console.log(galaxy));
As you can see, the code is flattened and contains a single chain of method calls. We have no "pyramid of doom".
Hence, callback hell is avoided.
In case you were wondering, promises are another way to avoid callback hell, but promises are eager, not lazy like observables and (generally speaking) you cannot cancel them as easily.
Just answer the question: could you please also show how RX solves the "callback hell problem" on that simple example?
The magic is flatMap. We can write the following code in Rx for #hugomg's example:
def getData() = Observable[X]
getData().flatMap(x -> Observable[Y])
.flatMap(y -> Observable[Z])
.map(z -> ...)...
It's like you are writing some synchronous FP codes, but actually you can make them asynchronous by Scheduler.
Callback hell is any code where the use of function callbacks in async code becomes obscure or difficult to follow. Generally, when there is more than one level of indirection, code using callbacks can become harder to follow, harder to refactor, and harder to test. A code smell is multiple levels of indentation due to passing multiple layers of function literals.
This often happens when behaviour has dependencies, i.e. when A must happen before B must happen before C. Then you get code like this:
a({
parameter : someParameter,
callback : function() {
b({
parameter : someOtherParameter,
callback : function({
c(yetAnotherParameter)
})
}
});
If you have lots of behavioural dependencies in your code like this, it can get troublesome fast. Especially if it branches...
a({
parameter : someParameter,
callback : function(status) {
if (status == states.SUCCESS) {
b(function(status) {
if (status == states.SUCCESS) {
c(function(status){
if (status == states.SUCCESS) {
// Not an exaggeration. I have seen
// code that looks like this regularly.
}
});
}
});
} elseif (status == states.PENDING {
...
}
}
});
This won't do. How can we make asynchronous code execute in a determined order without having to pass all these callbacks around?
RX is short for 'reactive extensions'. I haven't used it, but Googling suggests it's an event-based framework, which makes sense. Events are a common pattern to make code execute in order without creating brittle coupling. You can make C listen to the event 'bFinished' which only happens after B is called listening to 'aFinished'. You can then easily add extra steps or extend this kind of behaviour, and can easily test that your code executes in order by merely broadcasting events in your test case.
Call back hell means you are inside of a callback of inside another callback and it goes to nth call until your needs not fullfiled.
Let's understand through an example of fake ajax call by using set timeout API, lets assume we have a recipe API, we need to download all recipe.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
In the above example after 1.5 sec when timer expires inside code of call back will execute, in other words, through our fake ajax call all recipe will downloaded from the server. Now we need to download a particular recipe data.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
To download a particular recipe data we wrote code inside of our first callback and passed recipe Id.
Now let's say we need to download all the recipes of the same publisher of the recipe which id is 7638.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
setTimeout(publisher=>{
const recipe2 = {title:'Fresh Apple Pie', publisher:'Suru'};
console.log(recipe2);
}, 1500, recipe.publisher);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
To full-fill our needs which is to download all the recipes of publisher name suru, we wrote code inside of our second call back. It is clear we wrote a callback chain which is called callback hell.
If you want to avoid callback hell, you can use Promise, which is js es6 feature, each promise takes a callback which is called when a promise is full-filled. promise callback has two options either it is resolved or reject. Suppose your API call is successful you can call resolve and pass data through the resolve, you can get this data by using then(). But if your API failed you can use reject, use catch to catch the error. Remember a promise always use then for resolve and catch for reject
Let's solve the previous callback hell problem using a promise.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
getIds.then(IDs=>{
console.log(IDs);
}).catch(error=>{
console.log(error);
});
</script>
</body>
Now download particular recipe:
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
getIds.then(IDs=>{
console.log(IDs);
return getRecipe(IDs[2]);
}).
then(recipe =>{
console.log(recipe);
})
.catch(error=>{
console.log(error);
});
</script>
</body>
Now we can write another method call allRecipeOfAPublisher like getRecipe which will also return a promise, and we can write another then() to receive resolve promise for allRecipeOfAPublisher, I hope at this point you can do it by yourself.
So we learned how to construct and consumed promises, now let's make consuming a promise easier by using async/await which is introduced in es8.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
getRecipesAw();
</script>
</body>
In the above example, we used an async function because it will run in the background, inside async function we used await keyword before each method which returns or is a promise because to wait on that position until that promise fulfilled, in other words in the bellow codes until getIds completed resolved or reject program will stop executing codes bellow that line when IDs returned then we again called getRecipe() function with a id and waited by using await keyword until data returned. So this is how finally we recovered from the callback hell.
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
To use await we will need a async function, we can return a promise so use then for resolve promise and cath for reject promise
from the above example:
async function getRecipesAw(){
const IDs = await getIds;
const recipe = await getRecipe(IDs[2]);
return recipe;
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});
One way Callback hell can be avoided is to use FRP which is an "enhanced version" of RX.
I started to use FRP recently because I have found a good implementation of it called Sodium ( http://sodium.nz/ ).
A typical code looks like this ( Scala.js ) :
def render: Unit => VdomElement = { _ =>
<.div(
<.hr,
<.h2("Note Selector"),
<.hr,
<.br,
noteSelectorTable.comp(),
NoteCreatorWidget().createNewNoteButton.comp(),
NoteEditorWidget(selectedNote.updates()).comp(),
<.hr,
<.br
)
}
selectedNote.updates() is a Stream which fires if selectedNode (which is a Cell) changes, the NodeEditorWidget then updates correspondingly.
So, depending on the content of the selectedNode Cell, the currently edited Note will change.
This code avoids Callback-s entirely, almost, Cacllback-s are pushed to the "outer layer"/"surface" of the app, where the state handling logic interfaces with the external world. There are no Callbacks needed to propagate data within the internal state handling logic (which implements a state machine).
The full source code is here
The code snippet above corrosponds to the following simple Create / Display / Update example :
This code also sends updates to the server, so changes to the updated Entities are saved to the server automatically.
All the event handling is taken care by using Streams and Cells. These are FRP concepts. Callbacks are only needed where the FRP logic interfaces with the external world, such as user input, editing text, pressing a button, AJAX call returns.
Data flow is explicitly described, in a declarative manner using FRP (implemented by the Sodium library), so no event handling / callback logic is needed to describe data flow.
FRP (which is a more "strict" version of RX) is a way to describe a data flow graph, which can contain nodes that contain state. Events trigger state changes in the state containing nodes (called Cells).
Sodium is a higher order FRP library, meaning that using the flatMap/switch primitive one can rearrange the data flow graph at runtime.
I recommend to have a look into the Sodium book, it explains in detail how FRP gets rid of all Callbacks which are not essential for describing dataflow logic that has to do with updating the applications state in response to some external stimuli.
Using FRP, only those Callbacks need to be kept which describe interaction with the external world. In other words, the dataflow is described in a functional / declarative manner when one uses an FRP framework (such as Sodium), or when one uses an "FRP like" framework (such as RX).
Sodium is also available for Javascript/Typescript.
Use jazz.js
https://github.com/Javanile/Jazz.js
it simplify like this:
// run sequential task chained
jj.script([
// first task
function(next) {
// at end of this process 'next' point to second task and run it
callAsyncProcess1(next);
},
// second task
function(next) {
// at end of this process 'next' point to thirt task and run it
callAsyncProcess2(next);
},
// thirt task
function(next) {
// at end of this process 'next' point to (if have)
callAsyncProcess3(next);
},
]);
If you don't have a knowledge about callback and hell callback there is no problem.Ist thing is that call back and call back hell.For example:hell call back is like a we can store a class inside a class.As you heard about that nested in C, C++ language.Nested Means that a class inside a another class.

What is "callback hell" and how and why does RX solve it?

Can someone give a clear definition together with a simple example that explains what is a "callback hell" for someone who does not know JavaScript and node.js ?
When (in what kind of settings) does the "callback hell problem" occur?
Why does it occur?
Is "callback hell" always related to asynchronous computations?
Or can "callback hell" occur also in a single threaded application?
I took the Reactive Course at Coursera and Erik Meijer said in one of his lectures that RX solves the problem of "callback hell". I asked what is a "callback hell" on the Coursera forum but I got no clear answer.
After explaining "callback hell" on a simple example, could you also show how RX solves the "callback hell problem" on that simple example?
1) What is a "callback hell" for someone who does not know javascript and node.js ?
This other question has some examples of Javascript callback hell: How to avoid long nesting of asynchronous functions in Node.js
The problem in Javascript is that the only way to "freeze" a computation and have the "rest of it" execute latter (asynchronously) is to put "the rest of it" inside a callback.
For example, say I want to run code that looks like this:
x = getData();
y = getMoreData(x);
z = getMoreData(y);
...
What happens if now I want to make the getData functions asynchronous, meaning that I get a chance to run some other code while I am waiting for them to return their values? In Javascript, the only way would be to rewrite everything that touches an async computation using continuation passing style:
getData(function(x){
getMoreData(x, function(y){
getMoreData(y, function(z){
...
});
});
});
I don't think I need to convince anyone that this version is uglier than the previous one. :-)
2) When (in what kind of settings) does the "callback hell problem" occur?
When you have lots of callback functions in your code! It gets harder to work with them the more of them you have in your code and it gets particularly bad when you need to do loops, try-catch blocks and things like that.
For example, as far as I know, in JavaScript the only way to execute a series of asynchronous functions where one is run after the previous returns is using a recursive function. You can't use a for loop.
// we would like to write the following
for(var i=0; i<10; i++){
doSomething(i);
}
blah();
Instead, we might need to end up writing:
function loop(i, onDone){
if(i >= 10){
onDone()
}else{
doSomething(i, function(){
loop(i+1, onDone);
});
}
}
loop(0, function(){
blah();
});
//ugh!
The number of questions we get here on StackOverflow asking how to do this kind of thing is a testament to how confusing it is :)
3) Why does it occur ?
It occurs because in JavaScript the only way to delay a computation so that it runs after the asynchronous call returns is to put the delayed code inside a callback function. You cannot delay code that was written in traditional synchronous style so you end up with nested callbacks everywhere.
4) Or can "callback hell" occur also in a single threaded application?
Asynchronous programming has to do with concurrency while a single-thread has to do with parallelism. The two concepts are actually not the same thing.
You can still have concurrent code in a single threaded context. In fact, JavaScript, the queen of callback hell, is single threaded.
What is the difference between concurrency and parallelism?
5) could you please also show how RX solves the "callback hell problem" on that simple example.
I don't know anything about RX in particular, but usually this problem gets solved by adding native support for asynchronous computation in the programming language. The implementations can vary and include: async, generators, coroutines, and callcc.
In Python we can implement that previous loop example with something along the lines of:
def myLoop():
for i in range(10):
doSomething(i)
yield
myGen = myLoop()
This is not the full code but the idea is that the "yield" pauses our for loop until someone calls myGen.next(). The important thing is that we could still write the code using a for loop, without needing to turn out logic "inside out" like we had to do in that recursive loop function.
To address the question of how Rx solves callback hell:
First let's describe callback hell again.
Imagine a case were we must do http to get three resources - person, planet and galaxy. Our objective is to find the galaxy the person lives in. First we must get the person, then the planet, then the galaxy. That's three callbacks for three asynchronous operations.
getPerson(person => {
getPlanet(person, (planet) => {
getGalaxy(planet, (galaxy) => {
console.log(galaxy);
});
});
});
Each callback is nested. Each inner callback is dependent on its parent. This leads to the "pyramid of doom" style of callback hell. The code looks like a > sign.
To solve this in RxJs you could do something like so:
getPerson()
.map(person => getPlanet(person))
.map(planet => getGalaxy(planet))
.mergeAll()
.subscribe(galaxy => console.log(galaxy));
With the mergeMap AKA flatMap operator you could make it more succinct:
getPerson()
.mergeMap(person => getPlanet(person))
.mergeMap(planet => getGalaxy(planet))
.subscribe(galaxy => console.log(galaxy));
As you can see, the code is flattened and contains a single chain of method calls. We have no "pyramid of doom".
Hence, callback hell is avoided.
In case you were wondering, promises are another way to avoid callback hell, but promises are eager, not lazy like observables and (generally speaking) you cannot cancel them as easily.
Just answer the question: could you please also show how RX solves the "callback hell problem" on that simple example?
The magic is flatMap. We can write the following code in Rx for #hugomg's example:
def getData() = Observable[X]
getData().flatMap(x -> Observable[Y])
.flatMap(y -> Observable[Z])
.map(z -> ...)...
It's like you are writing some synchronous FP codes, but actually you can make them asynchronous by Scheduler.
Callback hell is any code where the use of function callbacks in async code becomes obscure or difficult to follow. Generally, when there is more than one level of indirection, code using callbacks can become harder to follow, harder to refactor, and harder to test. A code smell is multiple levels of indentation due to passing multiple layers of function literals.
This often happens when behaviour has dependencies, i.e. when A must happen before B must happen before C. Then you get code like this:
a({
parameter : someParameter,
callback : function() {
b({
parameter : someOtherParameter,
callback : function({
c(yetAnotherParameter)
})
}
});
If you have lots of behavioural dependencies in your code like this, it can get troublesome fast. Especially if it branches...
a({
parameter : someParameter,
callback : function(status) {
if (status == states.SUCCESS) {
b(function(status) {
if (status == states.SUCCESS) {
c(function(status){
if (status == states.SUCCESS) {
// Not an exaggeration. I have seen
// code that looks like this regularly.
}
});
}
});
} elseif (status == states.PENDING {
...
}
}
});
This won't do. How can we make asynchronous code execute in a determined order without having to pass all these callbacks around?
RX is short for 'reactive extensions'. I haven't used it, but Googling suggests it's an event-based framework, which makes sense. Events are a common pattern to make code execute in order without creating brittle coupling. You can make C listen to the event 'bFinished' which only happens after B is called listening to 'aFinished'. You can then easily add extra steps or extend this kind of behaviour, and can easily test that your code executes in order by merely broadcasting events in your test case.
Call back hell means you are inside of a callback of inside another callback and it goes to nth call until your needs not fullfiled.
Let's understand through an example of fake ajax call by using set timeout API, lets assume we have a recipe API, we need to download all recipe.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
In the above example after 1.5 sec when timer expires inside code of call back will execute, in other words, through our fake ajax call all recipe will downloaded from the server. Now we need to download a particular recipe data.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
To download a particular recipe data we wrote code inside of our first callback and passed recipe Id.
Now let's say we need to download all the recipes of the same publisher of the recipe which id is 7638.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
setTimeout(publisher=>{
const recipe2 = {title:'Fresh Apple Pie', publisher:'Suru'};
console.log(recipe2);
}, 1500, recipe.publisher);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
To full-fill our needs which is to download all the recipes of publisher name suru, we wrote code inside of our second call back. It is clear we wrote a callback chain which is called callback hell.
If you want to avoid callback hell, you can use Promise, which is js es6 feature, each promise takes a callback which is called when a promise is full-filled. promise callback has two options either it is resolved or reject. Suppose your API call is successful you can call resolve and pass data through the resolve, you can get this data by using then(). But if your API failed you can use reject, use catch to catch the error. Remember a promise always use then for resolve and catch for reject
Let's solve the previous callback hell problem using a promise.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
getIds.then(IDs=>{
console.log(IDs);
}).catch(error=>{
console.log(error);
});
</script>
</body>
Now download particular recipe:
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
getIds.then(IDs=>{
console.log(IDs);
return getRecipe(IDs[2]);
}).
then(recipe =>{
console.log(recipe);
})
.catch(error=>{
console.log(error);
});
</script>
</body>
Now we can write another method call allRecipeOfAPublisher like getRecipe which will also return a promise, and we can write another then() to receive resolve promise for allRecipeOfAPublisher, I hope at this point you can do it by yourself.
So we learned how to construct and consumed promises, now let's make consuming a promise easier by using async/await which is introduced in es8.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
getRecipesAw();
</script>
</body>
In the above example, we used an async function because it will run in the background, inside async function we used await keyword before each method which returns or is a promise because to wait on that position until that promise fulfilled, in other words in the bellow codes until getIds completed resolved or reject program will stop executing codes bellow that line when IDs returned then we again called getRecipe() function with a id and waited by using await keyword until data returned. So this is how finally we recovered from the callback hell.
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
To use await we will need a async function, we can return a promise so use then for resolve promise and cath for reject promise
from the above example:
async function getRecipesAw(){
const IDs = await getIds;
const recipe = await getRecipe(IDs[2]);
return recipe;
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});
One way Callback hell can be avoided is to use FRP which is an "enhanced version" of RX.
I started to use FRP recently because I have found a good implementation of it called Sodium ( http://sodium.nz/ ).
A typical code looks like this ( Scala.js ) :
def render: Unit => VdomElement = { _ =>
<.div(
<.hr,
<.h2("Note Selector"),
<.hr,
<.br,
noteSelectorTable.comp(),
NoteCreatorWidget().createNewNoteButton.comp(),
NoteEditorWidget(selectedNote.updates()).comp(),
<.hr,
<.br
)
}
selectedNote.updates() is a Stream which fires if selectedNode (which is a Cell) changes, the NodeEditorWidget then updates correspondingly.
So, depending on the content of the selectedNode Cell, the currently edited Note will change.
This code avoids Callback-s entirely, almost, Cacllback-s are pushed to the "outer layer"/"surface" of the app, where the state handling logic interfaces with the external world. There are no Callbacks needed to propagate data within the internal state handling logic (which implements a state machine).
The full source code is here
The code snippet above corrosponds to the following simple Create / Display / Update example :
This code also sends updates to the server, so changes to the updated Entities are saved to the server automatically.
All the event handling is taken care by using Streams and Cells. These are FRP concepts. Callbacks are only needed where the FRP logic interfaces with the external world, such as user input, editing text, pressing a button, AJAX call returns.
Data flow is explicitly described, in a declarative manner using FRP (implemented by the Sodium library), so no event handling / callback logic is needed to describe data flow.
FRP (which is a more "strict" version of RX) is a way to describe a data flow graph, which can contain nodes that contain state. Events trigger state changes in the state containing nodes (called Cells).
Sodium is a higher order FRP library, meaning that using the flatMap/switch primitive one can rearrange the data flow graph at runtime.
I recommend to have a look into the Sodium book, it explains in detail how FRP gets rid of all Callbacks which are not essential for describing dataflow logic that has to do with updating the applications state in response to some external stimuli.
Using FRP, only those Callbacks need to be kept which describe interaction with the external world. In other words, the dataflow is described in a functional / declarative manner when one uses an FRP framework (such as Sodium), or when one uses an "FRP like" framework (such as RX).
Sodium is also available for Javascript/Typescript.
Use jazz.js
https://github.com/Javanile/Jazz.js
it simplify like this:
// run sequential task chained
jj.script([
// first task
function(next) {
// at end of this process 'next' point to second task and run it
callAsyncProcess1(next);
},
// second task
function(next) {
// at end of this process 'next' point to thirt task and run it
callAsyncProcess2(next);
},
// thirt task
function(next) {
// at end of this process 'next' point to (if have)
callAsyncProcess3(next);
},
]);
If you don't have a knowledge about callback and hell callback there is no problem.Ist thing is that call back and call back hell.For example:hell call back is like a we can store a class inside a class.As you heard about that nested in C, C++ language.Nested Means that a class inside a another class.

Categories

Resources