yandex
loader

please wait

  • Jai Khanna Feb-15-2019 10:53:01 AM ( 1 month ago )

     

    I want to work with promises but I have a callback API in a format like:

    1. DOM load or other one time event:

    window.onload; // set to callback
    ...
    window.onload = function() {
    
    };

    2. Plain callback:

    function request(onChangeHandler) {
        ...
    }
    request(function() {
        // change happened
        ...
    });

    3. Node style callback ("nodeback"):

    function getStuff(dat, callback) {
        ...
    }
    getStuff("dataParam", function(err, data) {
        ...
    })

    4. A whole library with node style callbacks:

    API;
    API.one(function(err, data) {
        API.two(function(err, data2) {
            API.three(function(err, data3) {
                ...
            });
        });
    });

    How do I work with the API in promises, how do I "promisify" it?

  • Alice Davidson Feb-15-2019 10:58:58 AM ( 1 month ago )

    Promises have state, they start as pending and can settle to:

    • fulfilled meaning that the computation completed successfully.
    • rejected meaning that the computation failed.

    Promise returning functions should never throw, they should return rejections instead. Throwing from a promise returning function will force you to use both a } catch { and a .catch. People using promisified APIs do not expect promises to throw. If you're not sure how async APIs work in JS - please see this answer first.

    1. DOM load or other one time event:

    So, creating promises generally means specifying when they settle - that means when they move to the fulfilled or rejected phase to indicate the data is available (and can be accessed with .then).

    With modern promise implementations that support the Promise constructor like native ES6 promises:

    function load() {
        return new Promise(function(resolve, reject) {
            window.onload = resolve;
        });
    }

    You would then use the resulting promise like so:

    load().then(function() {
        // Do things after onload
    });

    With libraries that support deferred (Let's use $q for this example here, but we'll also use jQuery later):

    function load() {
        var d = $q.defer();
        window.onload = function() { d.resolve(); };
        return d.promise;
    }

    Or with a jQuery like API, hooking on an event happening once:

    function done() {
        var d = $.Deferred();
        $("#myObject").once("click",function() {
            d.resolve();
        });
        return d.promise();
    }

    2. Plain callback:

    These APIs are rather common since well… callbacks are common in JS. Let's look at the common case of having onSuccess and onFail:

    function getUserData(userId, onLoad, onFail) { 

    With modern promise implementations that support the Promise constructor like native ES6 promises:

    function getUserDataAsync(userId) {
        return new Promise(function(resolve, reject) {
            getUserData(userId, resolve, reject);
        });
    }

    With libraries that support deferred (Let's use jQuery for this example here, but we've also used $q above):

    function getUserDataAsync(userId) {
        var d = $.Deferred();
        getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
        return d.promise
  • James Watson Feb-15-2019 11:01:14 AM ( 1 month ago )

    Today, I can use Promise in Node.js as a plain Javascript method.

    A simple and basic example to Promise (with KISS way):

    Plain Javascript Async API code:

    function divisionAPI (number, divider, successCallback, errorCallback) {
    
        if (divider == 0) {
            return errorCallback( new Error("Division by zero") )
        }
    
        successCallback( number / divider )
    
    }

    Promise Javascript Async API code:

    function divisionAPI (number, divider) {
    
        return new Promise(function (fulfilled, rejected) {
    
            if (divider == 0) {
                return rejected( new Error("Division by zero") )
            }
    
            fulfilled( number / divider )
    
         })
    
    }

    (I recommend visiting this beautiful source)

    Also Promise can be used with together async\await in ES7 to make the program flow wait for a fullfiled result like the following:

    function getName () {
    
        return new Promise(function (fulfilled, rejected) {
    
            var name = "John Doe";
    
            // wait 3000 milliseconds before calling fulfilled() method
            setTimeout ( 
                function() {
                    fulfilled( name )
                }, 
                3000
            )
    
        })
    
    }
    
    
    async function foo () {
    
        var name = await getName(); // awaits for a fulfilled result!
    
        console.log(name); // the console writes "John Doe" after 3000 milliseconds
    
    }
    
    
    foo() // calling the foo() method to run the code

    Another usage with the same code by using .then() method

    function getName () {
    
        return new Promise(function (fulfilled, rejected) {
    
            var name = "John Doe";
    
            // wait 3000 milliseconds before calling fulfilled() method
            setTimeout ( 
                function() {
                    fulfilled( name )
                }, 
                3000
            )
    
        })
    
    }
    
    
    // the console writes "John Doe" after 3000 milliseconds
    getName().then(function(name){ console.log(name) })

    Promise can also be used on any platform that is based on Node.js like 

  • Amie Khalifa Feb-15-2019 11:02:21 AM ( 1 month ago )

    Before converting a function as promise In Node.JS

    var request = require('request'); //http wrapped module
    
    function requestWrapper(url, callback) {
        request.get(url, function (err, response) {
          if (err) {
            callback(err);
          }else{
            callback(null, response);             
          }      
        })
    }
    
    
    requestWrapper(url, function (err, response) {
        console.log(err, response)
    })

    After Converting It

    var request = require('request');
    var Promise = require('bluebird');
    
    function requestWrapper(url) {
      return new Promise(function (resolve, reject) { //returning promise
        request.get(url, function (err, response) {
          if (err) {
            reject(err); //promise reject
          }else{
            resolve(response); //promise resolve
          }
        })
      })
    }
    
    
    requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
        console.log(response) //resolve callback(success)
    }).catch(function(error){
        console.log(error) //reject callback(failure)
    })

    Incase you need to handle multiple request

    var allRequests = [];
    allRequests.push(requestWrapper('http://localhost:8080/promise_request/1')) 
    allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
    allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))    
    
    Promise.all(allRequests).then(function (results) {
      console.log(results);//result will be array which contains each promise response
    }).catch(
  • NeelKamal Jha Feb-15-2019 11:04:00 AM ( 1 month ago )

    I don't think the window.onload suggestion by @Benjamin will work all the time, as it doesn't detect whether it is called after the load. I have been bitten by that many times. Here is a version which should always work:

    function promiseDOMready() {
        return new Promise(function(resolve) {
            if (document.readyState === "complete") return resolve();
            document.addEventListener("DOMContentLoaded", resolve);
        });
    }
    promiseDOMready().then(initOnLoad);
     
  • Garry Buttler Feb-15-2019 11:06:55 AM ( 1 month ago )

    In release candidate for Node.js 8.0.0, there's a new utility, util.promisify (I've written about util.promisify), that encapsulates the capacity of promisifying whatever function.

    It is not much different from the approaches suggested in the other answers, but has the advantage of being a core method, and not requiring additional dependencies.

    const fs = require('fs');
    const util = require('util');
    
    const readFile = util.promisify(fs.readFile);

    Then you've a readFile method that returns a native Promise.

    readFile('./notes.txt')
      .then(txt => console.log(txt))
      .catch(...);

     
  • Dilpreet Kaur Feb-15-2019 11:09:25 AM ( 1 month ago )

    You can use JavaScript native promises with Node JS.

    My Cloud 9 code link: https://ide.c9.io/adx2803/native-promises-in-node

    /**
    * 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('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
            var obj = JSON.parse(result);
            return promisify('http://jsonplaceholder.typicode.com/users/' + 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
     
  • Sarah Jones Feb-15-2019 11:11:29 AM ( 1 month ago )

    The Q library by kriskowal includes callback-to-promise functions. A method like this:

    obj.prototype.dosomething(params, cb) {
      ...blah blah...
      cb(error, results);
    }

    can be converted with Q.ninvoke

    Q.ninvoke(obj,"dosomething",params).
    then(function(results) {
    });
  • Yasmin Mirza Feb-15-2019 11:19:35 AM ( 1 month ago )

    With plain old vanilla javaScript, here's a solution to promisify an api callback.

    function get(url, callback) {
            var xhr = new XMLHttpRequest();
            xhr.open('get', url);
            xhr.addEventListener('readystatechange', function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        console.log('successful ... should call callback ... ');
                        callback(null, JSON.parse(xhr.responseText));
                    } else {
                        console.log('error ... callback with error data ... ');
                        callback(xhr, null);
                    }
                }
            });
            xhr.send();
        }
    
    /**
         * @function promisify: convert api based callbacks to promises
         * @description takes in a factory function and promisifies it
         * @params {function} input function to promisify
         * @params {array} an array of inputs to the function to be promisified
         * @return {function} promisified function
         * */
        function promisify(fn) {
            return function () {
                var args = Array.prototype.slice.call(arguments);
                return new Promise(function(resolve, reject) {
                    fn.apply(null, args.concat(function (err, result) {
                        if (err) reject(err);
                        else resolve(result);
                    }));
                });
            }
        }
    
    var get_promisified = promisify(get);
    var promise = get_promisified('some_url');
    promise.then(function (data) {
            // corresponds to the resolve function
            console.log('successful operation: ', data);
    }, function (error) {
            console.log(error);
    });
     
  • Kajal Gaur Feb-15-2019 11:21:02 AM ( 1 month ago )

    In Node.js 8 you can promisify object methods on the fly using this npm module:

    https://www.npmjs.com/package/doasync

    It uses util.promisify and Proxies so that your objects stay unchanged. Memoization is also done with the use of WeakMaps). Here are some examples:

    With objects:

    const fs = require('fs');
    const doAsync = require('doasync');
    
    doAsync(fs).readFile('package.json', 'utf8')
      .then(result => {
        console.dir(JSON.parse(result), {colors: true});
      });

    With functions:

    doAsync(request)('http://www.google.com')
      .then(({body}) => {
        console.log(body);
        // ...
      });

    You can even use native call and apply to bind some context:

    doAsync(myFunc).apply(context, params)
      .then(result => { /*...*/ });
     

Please login

Similar Discussion

Recommended For You