I have seen different ways of doing multiple dependent ajax synchronous call. Two of which is being widely adopted is the jquery defer method and callback on success.
My question is:
1) What is the advantage of using one over another?
2) In what situation is one is preferred over another?
3) Is there any other better method than these 2?
// jquery defer method
var defer = $.when(
$.get('ajax_call_1');
);
defer.done(function () {
$.get('ajax_call_2');
});
// callback on success
$(function(){
$.ajax({
url:'/ajax_call_1',
data: { },
success: function(data){
$.get('ajax_call_2');
}
});
}
});
Some reasons to use Promises over Callbacks:
Much simpler to sequence multiple asynchronous operations.
Much simpler to build conditional logic involving multiple asynchronous operations.
Much simpler to do robust error handling involving multiple asynchronous operations.
Much simpler to build reusable asynchronous interfaces.
Much simpler to interface with other asynchronous interfaces.
Much simpler to deal with exceptions that might occur deep in asynchronous code that would otherwise cause silent failure
In your question, the simplest way to sequence jQuery Ajax calls and catch all possible errors is to use the natural promises returned from $.ajax() and chain them:
$.get('ajax_call_1').then(function(value) {
return $.get('ajax_call_2');
}).then(function(result) {
// success with both here
}, function(err) {
// error with one of them here
});
Or, with no error handling like in your example:
$.get('ajax_call_1').then(function(value) {
$.get('ajax_call_2');
})
There is no reason to use this construct here:
// jquery defer method
var defer = $.when(
$.get('ajax_call_1');
);
because $.get() already returns a promise so there is no need to use $.when() to just create yet another promise. $.when() is useful when you have more than one promise and you want to know when all of them are done. For one promise, you just use it directly - no reason to use $.when() with a single promise.
You can do it your second way:
// callback on success
$.ajax({
url:'/ajax_call_1',
data: { },
success: function(data){
$.get('ajax_call_2');
}
});
As this is just the non-promise way of coding with nested callbacks. The major disadvantage is that propagation of errors and sequencing multiple operations gets messy and difficult when not using promises. In just this simple example, try to get the error from either of the ajax calls back to the caller. It takes a lot of extra code to do that. My promise example above propagates all errors back to the caller for you.
As for your specific questions:
1) What is the advantage of using one over another?
You're basically asking why use promises over nested callbacks. There are hundreds of articles on the advantages of using promises. I will see if I can find one or two, but a Google search for "why promises vs. callbacks" should get you started on some reading.
What’s so great about JavaScript Promises?
Staying Sane with Asynchronous Programming
Why Am I Switching to Promises
2) In what situation is one is preferred over another?
I know of no reason why plain nested callbacks is preferred over using promises. Once you have learned promises, you will pretty much always find them a better way to code. The only reason I would not use promises is if I was trying to make code that was compatible with old browsers that did not have promises and even then, I'd probably just include a polyfill so that promises were supported.
3) Is there any other better method than these 2?
Yes, see my first code example.
P.S. Note that I choose to only use .then() with jQuery promises because that is the ES6 promise standard and it will make it easier in the future when jQuery transitions its promises to be more standards-compatible (which they are working on). Your code will also be more consistent when interfacing with other sources of promises that do use the standard.
P.P.S. Promises are one-shot devices. They either resolve or reject once and only once. If you are trying to get multiple notifications from some source, then promises are not built for that. An event emitter or a publish/subscribe system might be a better match for that type of problem.
Related
I have some older Node.js code that I'm updating. In the process I'm designing new modules to work with the old code. I'm finding that now, as opposed to when I first wrote this, I rely more on using ES6 promises rather than callbacks. So now I have this mix of some functions returning promises and some taking callbacks - which is tedious. I think eventually it should be refactored to use promises. But before that is done...
What are the situations where promises are preferred and where are callbacks preferred?
Is there any type of situation that a callback can handle better than a promise and vice-versa?
Based on what I've seen so far, I can't really see any reason to use callbacks instead of promises. Is that true?
First off, you pretty much never want to write code that is a mix of callbacks and promises for async operations. If you're moving to promises or introducing some promises, then you probably want to refactor the callbacks in that same section of code into promises. For the appropriate types of operations, there are so many advantages of promises over plain callbacks that it is well worth the effort to convert when already working in an area of code.
Promises are great for:
Monitoring synchronous operations
That need to notify only once (usually completion or error)
Coordinating or managing multiple asynchronous operations such as sequencing or branching async operations or managing multiple operations in flight at the same time
Propagating errors from nested or deeply nested async operations
Getting code ready for the use of async/await (or using it now with a transpiler)
Operations that fit the Promise model where there are only three states: pending, fulfilled and rejected and where the state transitions from pending => fulfilled or from pending => rejected can then not change (a single one-way transition).
Dynamically linking or chaining asynchronous operations (such as do these two async operations, examine the result, then decide which other async operations to do based on the intermediate result)
Managing a mix of asynchronous and synchronous operations
Automatically catching and propagating upwards any exceptions that occur in async completion callbacks (in plain callbacks these exceptions are sometimes silently hidden).
Plain callbacks are good for things that promises cannot do:
Synchronous notifications (such as the callback for Array.prototype.map())
Notifications that may occur more than once (and thus need to call the callback more than once). Promises are one-shot devices and cannot be used for repeat notifications.
Situations that cannot be mapped into the pending, fulfilled, rejected one-way state model.
And, I'd also add EventEmitter to the mix.
EventEmitters are great for:
Publish/subscribe type notifications
An interface with an event model, particular when events can occur more than once (like streams)
Loose couplings when 3rd party code wants to participate or monitor something without any more of an API than an eventEmitter. No API to design. Just make an eventEmitter public and define some events and the data that goes with them.
Notes about converting plain callback code to Promises
If your callbacks fit the node calling convention with the callback passed as the last argument and called like this callback(err, result), then you somewhat automatically wrap the parent function in a promise with util.promisify() in node.js or if using the Bluebird promise library, with Promise.promisify().
With Bluebird, you can even promisify an entire module (that uses async callbacks in the node.js calling convention) at once such as:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.writeFileAsync("file.txt", data).then(() => {
// done here
}).catch(err => {
// error here
});
In node.js version 8+
There is now util.promisify() which will convert an async function that uses the node.js async calling convention to a function that returns a promise.
Example from the doc:
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
// usage of promisified function
stat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
});
They both exist to solve the same problem, handle the result of an asnychronous function.
Callbacks tend to be more verbose and coordinating multiple asynchronous requests concurrently can lead to callback hell if you're not actively modularizing your functions. Error handling and tracing tends to be less straightforward and even confusing since there could be many Error objects that all go back to a single error further down the call stack. Errors, also need to be passed back to the original caller that can also lead to some head scratching when determining where the original Error was thrown if anonymous functions were used in the callback chain. One of the benefits of callbacks is that they are just plain old functions and don't require any additional understanding beyond knowing how an asynchronous operation works.
Promises are more common as they require less code, are more readable since they are written like synchronous functions, have a single error channel, can handle thrown errors and with util.promisify() being added in the latest version of Node.js, can convert Error-First Callbacks to promises. There's also async/await which is making its way into Node.js now as well, and they also interface with Promises.
This is totally opinion based, so it really is about what you're most comfortable with but, Promises and async/await are the evolution of the callback and enhance the asynchronous development experience. This isn't an exhaustive comparison by any means but rather, a high level look at both callbacks and promises.
I don't remember from where I got this stuff but might be helpful in understanding promises better.
Promises are not callbacks. A promise represents the future result of an asynchronous operation. Of course, writing them the way you do, you get little benefit. But if you write them the way they are meant to be used, you can write asynchronous code in a way that resembles synchronous code and is much more easy to follow:
ADVANTAGES
1. Readability over callbacks
2. Easy to catch errors.
3. Simultaneous callbacks
1. Readability over callbacks
Promises provide a more succinct and clear way of representing sequential asynchronous operations in javascript. They are effectively a different syntax for achieving the same effect as callbacks. The advantage is increased readability. Something like this
aAsync()
.then(bAsync)
.then(cAsync)
.done(finish);
is much more readable than the equivalent of passing each of those individual functions as callbacks, like
aAsync(function(){
return bAsync(function(){
return cAsync(function(){
finish()
})
})
});
2. Easy to catch errors.
Certainly, not much less code, but much more readable. But this is not the end. Let's discover the true benefits: What if you wanted to check for any error in any of the steps? It would be hell to do it with callbacks, but with promises, is a piece of cake:
api()
.then(function(result) {
return api2();
})
.then(function(result2){
return api3();
})
.then(function(result3){
// do work
})
.catch(function(error) {
//handle any error that may occur before this point
});
/* Pretty much the same as a try { ... } catch block.
Even better: */
api()
.then(function(result){
return api2(); })
.then(function(result2){
return api3(); })
.then(function(result3){
// do work
})
.catch(function(error) {
//handle any error that may occur before this point
})
.then(function() {
//do something whether there was an error or not
//like hiding an spinner if you were performing an AJAX request.
});
3. Simultaneous callbacks And even better:
What if those 3 calls to api, api2, api3 could run simultaneously (e.g. if they were AJAX calls) but you needed to wait for the three? Without promises, you should have to create some sort of counter. With promises, using the ES6 notation, is another piece of cake and pretty neat:
Promise.all([api(), api2(), api3()])
.then(function(result) {
//do work. result is an array containing the values of the three fulfilled promises.
})
.catch(function(error) {
//handle the error. At least one of the promises rejected.
});
Hope you see Promises in a new light now.
I came across promises as I am going through my journey on learning AngularJS and it has been good so far. Now, I wanted to learn more about using AngularJS optional library resource.js. However, I came across examples that confused me a lot. For example, the promise skeleton is basically like this example.
//post method to server
$http.post('api/school',newStudent).then(fetchStudents).then(function(response){
//do something
}, function(error){
//do something
});
and another example like this assuming we have a List factory
List.save(self.newStudent).$promise.then(fetchStudents).then(function(){
self.newStudent = {};
});
So my question is why the use of $promise? What is the use of it? It was not really explained in the book I am using and I am confuse on when to use it or not. Any clear explanation will be appreciated. Thanks
A service that helps you run functions asynchronously, and use their
return values (or exceptions) when they are done processing
Promises provide a simpler alternative for executing, composing, and managing asynchronous operations when compared to traditional callback-based approaches. They also allow you to handle asynchronous errors using approaches that are similar to synchronous try/catch.
Read more about it at :
https://docs.angularjs.org/api/ng/service/$q
http://haroldrv.com/2015/02/understanding-angularjs-q-service-and-promises/
http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls
I've got this problem that I couldn't find a solution for by googling.
I've got a library, that I'm using (and do not want to edit, unless it's really necessary) that allows the user to select an item, then calls my custom callback function to modify the item and then continues working with it.
I need to perform some asynchronous tasks on it, which may take some time. This creates a race condition as my async tasks have not yet finished when the callback function is finished and the library continues its work on the item.
library.onItemSelectionCallback = function (item) {
myService.modifyItem(item).then(
function (modifiedItemProperty) {
item.newProperty = modifiedItemProperty;
});
myService.anotherModifyItem(item).then(
function (modifiedItemProperty) {
item.existingProperty = modifiedItemProperty;
});
}
How do I wait for both of my async tasks to finish, before allowing this callback to finish?
Only thing I could think of is looping with while and sleep every hundred or so milliseconds until both of the promises have been resolved, but that doesn't seem to be a very good solution.
I understand that this makes async requests quite synchronous and might possibly be detrimental for UX, but do not really see another way out.
EDIT: I know that i'm risking with removing the generic nature of the question and thus making it too localized, I will say that I'm trying to use angular-file-upload module, specifically, trying to mount a custom imageService, that would resize the picture before it's upload. I'm mounting it on the onBeforeUploadItem callback. The idea is that creating the resized image may take a while and that is why I need to return a promise from my imageService, that needs to be resolved before upload.
If modifyItem and anotherModifyItem work independently (that is, one does not rely on the other), you can just pipe them both into $q.all, eg
library.onItemSelectionCallback = function(item) {
var promises = {
newProperty: myService.modifyItem(item),
existingProperty: myService.anotherModifyItem(item)
};
return $q.all(promises).then(function(values) {
return angular.extend(item, values);
});
}
This will return a promise that resolves with item.
For the first part of my question -- Yes, I guess the only way to really wait for those two promises to be resolved would be something with a while and sleep, making them synchronous, which would probably work and not even be that bad (except for the site pausing until the requests are fulfilled), but would make me feel very, very bad about myself as a person and how my actions affect this world.
It is not possible to correctly mix callbacks and promises without hacks afaik.
For the second part of my question -- as per comments of #georgeawg, figured that an AngularJS module that implements HTML5 API and callbacks instead of $http service and promises is not how a good AngularJS module should be implemented, and so I moved towards a different module ng-file-upload, which, even though one could argue is less stylish, does the job very well and in an Angular way (ng-file-upload provides a simple $upload service, that returns a promise. If you want to modify files before upload, suggested way is to simply $watch and catch the moment user drag-drops or selects a file.).
This question already has answers here:
Javascript: How to determine whether to promisefy a function?
(2 answers)
Closed 4 years ago.
I'm getting into generators and promises now and I've kind of gotten the handle of how they work. Now it's time to make my own functions which utilize these. There are guides out there explaining how to make them and what they are for but however they rarely discuss the appropriate times when one should be used.
I know this mainly has to lie with promises as generators just help the code writing look synchronous (among other things).
So my question is: When should I and when should I not promisify a function I have?
From my understanding if the cpu is being utilized 100% by the function then I should NOT promisify as there is no point.
If the cpu is being blocked and is waiting for something external such as waiting for something to download then I guess I should promisify that function.
Promises should be used when you have asynchronous operations that you want to execute in a sequence. Operations that are costly, like writing to a file/db, making a request to another service, so forth, usually have an asynchronous api, since doing those synchronously would block your single-threaded javascript application. In those cases, you either use something like promises for a cleaner code, you use named functions and explicitly call them one after the other as callbacks or you don't use anything and have yourself a pyramid of doom full of callbacks.
So, imagine you want to get the user data from the token you recieve in the http request, then get all the posts regarding him, and get a special holiday offer from one of your other services that you wanna stick in there with the request. With promises, you could do something like
router.get('/activities', function(req, res){
userRepo.findByToken(token).then(checkForOffer).then(activityRepo.getUserPosts).then(function(composite){
res.send({activities: composite.activities, offer: composite.offer});
}).fail(function(err){
//handle the error
});
})
This post paint a clearer picture of how and when you should use promises.
I've been reading a lot about React for the last 3 days, but I don't see much information about the use of promises, so I have that concern.
Is there any library for this?
How should I use promises in React?
React doesn't come with a promise library baked in like Angular with $http. You will have to find your own.
A few you can try:
Bluebird (personal recommendation)
jQuery's $ajax
Native promises (unless you actually have to support IE): http://caniuse.com/#feat=promises
Promise object is used for handling asynchronous computations which has some important guarantees that are difficult to handle with the callback method (the more old-school method of handling asynchronous code).
A Promise object is simply a wrapper around a value that may or may not be known when the object is instantiated and provides a method for handling the value after it is known (also known as resolved) or is unavailable for a failure reason (we'll refer to this as rejected).
Using a Promise object gives us the opportunity to associate functionality for an asynchronous operation's eventual success or failure (for whatever reason). It also allows us to treat these complex scenarios by using synchronous.
To see more at : https://www.npmjs.com/package/react-promise