Difference Callback, Promise and Event JavaScript/React-Native <-> Java/Android - javascript

I am reading about native modules in React-Native and Android.
The documentation distinguishes between
callbacks
promises
events
I am having trouble understaind the difference between the three of them. What are the main differences and when is used what?

A callback is a function that you pass to another function, which will then call that when some async action is done:
somethingAsync(function callback(result) { /*...*/ });
You will see this pattern quite often, as everything ilelse relies on callbacks. If you however got many callbacks, the code gets hard to read and to maintain, especially when working with loops. For that, Promises were introduced, which wrap a callback function, and allow to attach callbacks to the Promise. That allows for some nice chaining:
const promise = new Promise(somethingAsync);
promise.then(function result() { /*...*/ });
Note that a promise only resolves once, while callbacks can be called multiple times.
Events are not really related to Promises, they allow you to attach a callback to an object that will get called when something happens, e.g. a button gets clicked:
button.onclick = function(event) { /*...*/ }

Related

Javascript asynchronous handling without Promise and async/await

In this question, I just want to confirm that we cannot use callback to strictly handle asynchronous tasks in JavaScript.
For example, we use Promise.then or async/await:
myPromise().then(callback);
// or
(async () => {
const res = await myAsyncFunction();
callback(res);
})()
I saw many examples with callback but they used setTimeout:
const functionWithCallback = (asyncFunction, callback) => {
asyncFunction();
setTimeout(() => {
callback();
}, 1000);
};
The example above is NOT asynchronous handling to me because we don't know the time asyncFunction() complete. 1000ms here is just a number.
Do we have any way to handle it with callback only?
The example above is NOT asynchronous handling to me
You are right that the timing of the callback invocation does not depend on whether myAsyncFunction completed its asynchronous task or not. However, in the most common use of the terminology, setTimeout is calling its callback function asynchronously... always.
I just want to confirm that we cannot use callback to strictly handle asynchronous tasks in JavaScript.
You can. But there are several things to note:
Even promises work with a callback system: the then method takes a callback argument, and that callback will be executed when the promise is fulfilled. Promises do not abolish callbacks, but make it easier to work with them by allowing to chain and to avoid "callback hell".
Before promises were available in JavaScript, there surely was already the concept of asynchronous programming.
In your examples you provided a function myAsyncFunction. If it is important to react when its asynchronous tasks have completed, then surely that function must somehow notify of that completion.
Today it is very common for such an asynchronous function to return a promise, and then the caller will of course make use of that promise (with either then or await): that's the purpose of having the promise object. A known example of such an asynchronous function is fetch.
If myAsyncFunction does not return a promise, then we would expect such a function to notify in a different way. For instance, it could take a callback as argument. Then to code looks like this:
myAsyncFunction(callback);
Known examples of such asynchronous functions are setTimeout, requestAnimationFrame, and queueMicrotask
Still other asynchronous functions are more complex, as they may provide some synchronous results and other asynchronous results. They return an object to which a listener can be attached. The code will then look something like this:
let res = myAsyncFunction();
res.addEventListener("ready", callback);
There are many examples of this in the DOM API: for instance, document.createElement and the load event (typically used with img and script elements).
A slight variation of this, is where a constructor is called with new, or where the object is provided first, but the asynchronous action still has to be initiated by some event, or by a method call.
There are of course many variations to this, like:
let res = new MyConstructor();
res.myAsyncFunction();
res.onready = callback;
An example of such a constructor is XMLHttpRequest (with its send() method)
Conclusion
It really depends on how myAsyncFunction will notify that it has completed its asynchronous tasks. When myAsyncFunction returns a promise, then of course you should be using that promise. When not, there should be some way to provide your callback to the API that is offered.

Alternative to using callback function in JavaScript?

I'm trying to have the second function be called after the scrolling animation of the first one finishes. I've seen that callback functions are used in similar situations however they seem to be more cumbersome and difficult to read. Is there an simpler or more clean way to achieve the same result?
$('#nav_experience').click(function scrollToExperience(){
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500);
})
function navbarExperienceActive(){
scrollToExperience(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
Also I appreciate the second function is quite repetitive and there may be a more elegant way to write it, I'm relatively new to JavaScript.
One modern approach to situations where we used to use callbacks is to use promises, which are particularly effective when combined with async functions and await. (Conceptually, "promises" go by many names — promises, futures, deferreds....)
Promises themselves still use callbacks, but by providing a standardized form of passing around promises for future callbacks, they markedly improve code that used to pass callbacks around just as arguments.
Your scrollToExperience might look like this, for instance:
function scrollToExperience(){
return new Promise(resolve => {
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500, resolve);
});
}
navbarExperienceActive might use it like this:
function navbarExperienceActive(){
scrollToExperience().then(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
On the face of it, that hasn't changed much; you still have to pass a callback. But if navbarExperienceActive had to combine this with other asynchronous actions, chain off it in other ways, etc., using promises makes that simpler and more standard between codebases.
But if navbarExperienceActive were an async function, it could use await:
async function navbarExperienceActive(){
await scrollToExperience();
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
}
It still uses promises, but the code is written according to its simple logical flow rather than worrying about the fact that it has to wait for scrollToExperience to finish.
An async function always returns a promise; when you use await in the async function, if the value you pass it is a promise (hand-waves details about "thenables"), it returns its promise then settles that promise based on what happens to the promise you're awaiting (and/or the logic following it).
I should note that the promise returned by scrollToExperience above is a bit unusual, because it always fulfills the promise, it never rejects it. The code using its promise relies on that fact that it never rejects its promise.
In general, though, it's important to be sure to either handle promise rejection or pass the promise chain on to something else that will. That's another place where async functions make life simpler: They automatically propagate promise rejections, exactly the way synchronous functions automatically propagate exceptions.

Return data async inside emit

I have a background process written in node.js that is using the EventEmitter like this:
var event = { returnValue: undefined };
eventEmitter.emit('name', event, argument);
return event.returnValue; // Example of doing things with event.returnValue.
Other end of the event:
eventEmitter.on('name', (event, argument) => {
var returnValue = await asyncMethod(); // <- This method returns a Promise, so I could use await if possible or some other solution.
event.returnValue = returnValue;
});
I've tried to find an elegant solution to use asynchronous methods, but since EventEmitter does not support asynchronous functions at all, I can't really use await in the function or something similar.
One solution could be to set returnValue to a Promise, but that quickly becomes impractical, specially since some of my functions iterate through multiple asynchronous functions.
I need all the code to complete properly before the first block of code continues and tries to use the event.returnValue.
Is my only solution to use some third party "synchronize", or hasn't anyone at node.js thought of this problem?
There isn't really any problem for me if the thread is blocked while executing, since this is a background process without any GUI.
Since it doesn't really seem to exist any intuitive way to wait for a Promise to resolve synchronously without callbacks, or to use the EventEmitter with async callbacks, I wrote my own simple EventEmitter containing an array, and custom on and emit methods.
It handles asynchronous functions used as parameters properly so I can use it like this:
asyncEmitter.on('name', async (event, argument) => {
event.argument = await asyncMethod(); // Nice and clean code!
});
Of course I could develop it further create a once function and so on, but for me I really only depend on on and emit.
I wonder why the node team hasn't solved this yet?

How to rewrite this asynchronous method to return the value synchronously?

There are many questions on making a Nodejs/Javascript method synchronous, but the answers I have seen so far involved using libraries such as async and fibrous.
But to use libraries such as fibrous, I have to wrap my function with their wrapper.
I am seeking a solution where the code lies within my function (not outside and wrapping it).
For example, this is my async function which uses a callback:
function myFunc(callback) {
// Classic database fetch which is asynchronous
db.find("foo", function(err, results) {
callback(err, results);
});
}
What I want is for the function to return the results:
function myFunc() {
// Make this function synchronous, and return the result
// ...
return results;
}
How do I do that?
Once again, I don't want to wrap myFunc with other functions. I am thinking if a sleep loop works?
No, you can't use a loop to wait for an asynchronous call. Javascript is single threaded, so you need to return control to the main event handler for the asynchronous callback to be called. If you run a loop, the event that the database query is completed will just wait in the queue and never be handled.
What you can do is to return a promise instead of the result itself. That's an object that keeps track of whether the callback has been called or not, has a property where the callback can put the result, and has a method for getting the result when you need it (which uses a callback, because once you use an asynchrous method it can't be handled completely syncronously).
If you want an actual return value from an asynchronous function, you have no other choice than using either generators or Promises.
You will always have to wrap your functions, or return Promises directly.
One of the best promise libraries out there is bluebird, which also has an explanation for how and why to use it (https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them). If you need to interface with node style callbacks or need to expose an API that relies on node style callbacks instead of promises, it also comes with some convenience methods for automating that conversion.

JavaScript callback style - Moving to promises

I'm trying to work out how I can do my JavaScript callbacks in a different style.
My current style of callback, passes the callback into the function, and the function calls the callback. For example:
Function call
doSomething(function(data){
console.log(data);
});
Function
function doSomething(callback) {
// Call the callback
callback("someData");
}
This is the current style of callback that I'm using. But I've seen libraries that do their callbacks in a different style. For example:
Function call
doSomething().success(function(data){
console.log(data);
});
How does this work, and could anybody outline a simple example for me? Thanks for your time.
That is an implementation of the promise library. jQuery has an implementation called deferreds and another one is Q.
doSomething would look like something like this, using jQuery.
function doSomething() {
var dfd = $.deferred();
// do your logic
// eventually call dfd.resolve();
return dfd.promise();
}
Then calling it, use
doSomething().then(function() {
// do something else
});
What is nice about this pattern, is that you can have multiple callbacks and error callbacks.
The style that you're describing is generally called promises. jQuery has promises, but their documentation calls them "Deferreds" and it is an implementation of the Promises/A spec; there are a couple other promises libraries out there, including Q. (YUI also contains a promises implementation.)
There have been a bunch of recent (mid-2013) blog posts about promises, so it should be easy to find more information about them, both as a pattern and about specific implementations. It's worth digging into the source code of a couple of the implementations to see the nuts-and-bolts, but at a high-level, you can think of promises like this:
You wrap an asynchronous function in a promise and it is called.
The promise itself is then returned, meaning that you can save a reference to it in a variable.
The promise itself will be resolved (or "fulfilled") when the async function you called is complete.
You can then call done on the resolved promises, passing your callback function as the argument to done.
Isn't it simply this here:
Function
doSomething = new Object();
doSomething.success = function(callback) {
// Call the callback
callback("someData");
}
So it is just an Object extended with a member "success" that is a function.

Categories

Resources