Aren’t promises just callbacks?

Questions : Aren’t promises just callbacks?

I’ve been developing JavaScript for a few years and I don’t understand the fuss about promises at all.

It seems like all I do is change:

api(function(result){ api2(function(result2){ api3(function(result3){ // do work }); }); }); 

Which I could use a library like async for anyway, with something like:

api().then(function(result){ api2().then(function(result2){ api3().then(function(result3){ // do work }); }); }); 

Which is more code and less readable. I didn’t gain anything here, it’s not suddenly magically ‘flat’ either. Not to mention having to convert things to promises.

So, what’s the big fuss about promises here?

Total Answers: 11 Answers 11

Popular Answers:

  1. 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:

    api().then(function(result){ return api2(); }).then(function(result2){ return api3(); }).then(function(result3){ // do work }); 

    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. }); 

    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 contains 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.

  2. In addition to the already established answers, with ES6 arrow functions Promises turn from a modestly shining small blue dwarf straight into a red giant. That is about to collapse into a supernova:

    api().then(result => api2()).then(result2 => api3()).then(result3 => console.log(result3)) 

    As oligofren pointed out, without arguments between api calls you don’t need the anonymous wrapper functions at all:

    api().then(api2).then(api3).then(r3 => console.log(r3)) 

    And finally, if you want to reach a supermassive black hole level, Promises can be awaited:

    async function callApis() { let api1Result = await api(); let api2Result = await api2(api1Result); let api3Result = await api3(api2Result); return api3Result; } 
  3. In addition to the other answers, the ES2015 syntax blends seamlessly with promises, reducing even more boilerplate code:

    // Sequentially: api1() .then(r1 => api2(r1)) .then(r2 => api3(r2)) .then(r3 => { // Done }); // Parallel: Promise.all([ api1(), api2(), api3() ]).then(([r1, r2, r3]) => { // Done }); 
  4. Promises are not callbacks, both are programming idioms that facilitate async programming. Using an async/await-style of programming using coroutines or generators that return promises could be considered a 3rd such idiom. A comparison of these idioms across different programming languages (including Javascript) is here:

  5. No, Not at all.

    Callbacks are simply Functions In JavaScript which are to be called and then executed after the execution of another function has finished. So how it happens?

    Actually, In JavaScript, functions are itself considered as objects and hence as all other objects, even functions can be sent as arguments to other functions. The most common and generic use case one can think of is setTimeout() function in JavaScript.

    Promises are nothing but a much more improvised approach of handling and structuring asynchronous code in comparison to doing the same with callbacks.

    The Promise receives two Callbacks in constructor function: resolve and reject. These callbacks inside promises provide us with fine-grained control over error handling and success cases. The resolve callback is used when the execution of promise performed successfully and the reject callback is used to handle the error cases.

  6. No promises are just wrapper on callbacks

    example You can use javascript native promises with node js

    my cloud 9 code link : /** * Created by dixit-lab on 20/6/16. */ var express = require('express'); var request = require('request'); //Simplified HTTP request client. var app = express(); function promisify(url) { return new Promise(function (resolve, reject) { request.get(url, function (error, response, body) { if (!error && response.statusCode == 200) { resolve(body); } else { reject(error); } }) }); } //get all the albums of a user who have posted post 100 app.get('/listAlbums', function (req, res) { //get the post with post id 100 promisify('').then(function (result) { var obj = JSON.parse(result); return promisify('' + obj.userId + '/albums') }) .catch(function (e) { console.log(e); }) .then(function (result) { res.end(result); } ) }) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("Example app listening at http://%s:%s", host, port) }) //run webservice on browser : http://localhost:8081/listAlbums 
  7. JavaScript Promises actually use callback functions to determine what to do after a Promise has been resolved or rejected, therefore both are not fundamentally different. The main idea behind Promises is to take callbacks – especially nested callbacks where you want to perform a sort of actions, but it would be more readable.

  8. Promises overview:

    In JS we can wrap asynchronous operations (e.g database calls, AJAX calls) in promises. Usually we want to run some additional logic on the retrieved data. JS promises have handler functions which process the result of the asynchronous operations. The handler functions can even have other asynchronous operations within them which could rely on the value of the previous asynchronous operations.

    A promise always has of the 3 following states:

    1. pending: starting state of every promise, neither fulfilled nor rejected.
    2. fulfilled: The operation completed successfully.
    3. rejected: The operation failed.

    A pending promise can be resolved/fullfilled or rejected with a value. Then the following handler methods which take callbacks as arguments are called:

    1. Promise.prototype.then() : When the promise is resolved the callback argument of this function will be called.
    2. Promise.prototype.catch() : When the promise is rejected the callback argument of this function will be called.

    Although the above methods skill get callback arguments they are far superior than using only callbacks here is an example that will clarify a lot:


    function createProm(resolveVal, rejectVal) { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.5) { console.log("Resolved"); resolve(resolveVal); } else { console.log("Rejected"); reject(rejectVal); } }, 1000); }); } createProm(1, 2) .then((resVal) => { console.log(resVal); return resVal + 1; }) .then((resVal) => { console.log(resVal); return resVal + 2; }) .catch((rejectVal) => { console.log(rejectVal); return rejectVal + 1; }) .then((resVal) => { console.log(resVal); }) .finally(() => { console.log("Promise done"); });

    • The createProm function creates a promises which is resolved or rejected based on a random Nr after 1 second
    • If the promise is resolved the first then method is called and the resolved value is passed in as an argument of the callback
    • If the promise is rejected the first catch method is called and the rejected value is passed in as an argument
    • The catch and then methods return promises that’s why we can chain them. They wrap any returned value in Promise.resolve and any thrown value (using the throw keyword) in Promise.reject. So any value returned is transformed into a promise and on this promise we can again call a handler function.
    • Promise chains give us more fine tuned control and better overview than nested callbacks. For example the catch method handles all the errors which have occurred before the catch handler.
  9. Promises allows programmers to write simpler and far more readable code than by using callbacks.

    In a program, there are steps want to do in series.

    function f() { step_a(); step_b(); step_c(); ... } 

    There’s usually information carried between each step.

    function f() { const a = step_a( ); const b = step_b( a ); const c = step_c( b ); ... } 

    Some of these steps can take a (relatively) long time, so sometimes you want to do them in parallel with other things. One way to do that is using threads. Another is asynchronous programming. (Both approaches has pros and cons, which won’t be discussed here.) Here, we’re talking about asynchronous programming.

    The simple way to achieve the above when using asynchronous programming would be to provide a callback which is called once a step is complete.

    // step_* calls the provided function with the returned value once complete. function f() { step_a( function( a ) step_b( function( b ) step_c( ... ) }, ) }, ) } 

    That’s quite hard to read. Promises offer a way to flatten the code.

    // step_* returns a promise. function f() { step_a() .then( step_b ) .then( step_c ) ... } 

    The object returned is called a promise because it represents the future result (i.e. promised result) of the function (which could be a value or an exception).

    As much as promises help, it’s still a bit complicated to use promises. This is where async and await come in. In a function declared as async, await can be used in lieu of then.

    // step_* returns a promise. async function f() const a = await step_a( ); const b = await step_b( a ); const c = await step_c( b ); ... } 

    This is undeniably much much more readable than using callbacks.

  10. Now use height:100vh; for fixed window Height

    <style> .header-top{height:100vh; background:#000; color:#fff;display:flex;align-items:center;padding:10px; justify-content: space-around;} .header-top ul{list-style:none;padding:0; margin:0;display:flex;align-items:center; } .header-top ul li{padding:0px 10px;} </style> <div class="header-top"> <div class="logo">Hello</div> <ul> <li>Menu</li> <li>About Us</li> <li>Contact US</li> <li>Login</li> </ul> </div> 
  11. Try the following CSS:

    html { min-height: 100%; margin: 0; padding: 0; } body { height: 100%; } #right { min-height: 100%; } 
  12. This stuff will resize height of content automatically according to your browser. I hope this will work for you. Just try this example given below.

    You have to set up only height:100%.

    html,body { height: 100%; margin: 0; } .content { height: 100%; min-height: 100%; position: relative; } .content-left { height: auto; min-height: 100%; float: left; background: #ddd; width: 50%; position: relative; } #one { background: url( center center no-repeat scroll #aaa; width: 50%; position: relative; float: left; } #two { background: url( center center no-repeat scroll #520E24; width: 50%; float: left; position: relative; overflow-y: scroll; }
    <div class='content' id='one'></div> <div class='content-left' id='two'></div>

  13. If you use position: absolute; and jQuery, you could use

    $("#mydiv").css("height", $(document).height() + "px"); 
  14. You can use the following CSS to make a div 100% of the height of the browser window:

    display: block; position: relative; bottom: 0; height: 100%; 
  15. Stupidly easy solution which supports cross-domain and also supports browser re-size.

    <div style="height: 100vh;"> <iframe src="..." width="100%" height="80%"></iframe> </div> 

    Adjust the iframe height property as required (leave the div height property at 100vh).

    Why 80%? In my real-world scenario I have a header inside the div, before the iframe, which consumes some vertical space – so I set the iframe to use 80% instead of 100% (otherwise it would be the height of the containing div, but start after the header, and overflow out the bottom of the div).

  16. Even though this solution is done with jQuery I though it may be useful for anyone doing columns to fit the screen size.

    For columns starting at the top of the page, this solution is the simplest.

    body,html{ height:100%; } div#right{ height:100% } 

    For columns that are not starting at the top of the page (for example: if they are starting below the header).

    <script> $(document).ready(function () { var column_height = $("body").height(); column_height = column_height - 100; // 100 is the header height column_height = column_height + "px"; $("#column").css("height",column_height); }); </script> 

    First method applies the body height to it and the columns as well, which means that is starting_pixels + height100%.

    The second method gets the height of page shown to the user by getting the height of the body and then subtracts the header size to know how much height is left to display the column.

Tasg: javascript, callback