简体   繁体   中英

Q.all array of request promises, not sure how to get the results

Probably an obvious answer to this but I'm not sure what way to take. request is a node module: https://github.com/request/request I fill an array of getHistory requests (with different parameters). p = [p1,p2...].

this.app.all('/api/heatmap', function(req,res) {
   // fill p here _.each(blabla, p.push(gethistory(someparams...)
   var result = [];
   function getHistory(params) {
        var options = { ...};
        var callback = function(error, response, body) {
            if(error) { //wtv 
            } else {
              // what to do with the body here ? return body ? result.push(body) ?
            }
        }

        request(options, callback);
    }

    Q.all(p).then(function() {
    });
}

So the problem here is that I when all of the request to be done , put everything in an array/object then send the whole thing to the client. How to have getHistory returning the fetched value (after the request is done ).

Hope it's clear.

The core problem here is that node.js-style callbacks and promises are not compatible. Promises emphasize on return values, node emphasizes on callbacks.

Therefore you need a sort of adapter that wraps node's callback convention properly, a process called Promisifcation . This can be done manually, but it's tedious at best and error-prone when you are not careful. Luckily, since node's conventions are well-established, it can be automated. Q has a few helpers for that, but Bluebird is quite a bit more convenient in this regard.

So the easy way to do it is to switch to Bluebird as the promise library and to use promisifyAll .

var Promise = require('bluebird');
var request = Promise.promisifyAll(require("request"));

this.app.all('/api/heatmap', function(req, res) {
    var requests = blabla.map(function (item) {
        return request.getAsync({ /* params */ });
    });

    Promise.all(requests).then(function (responses) {
        res.send( JSON.stringify(responses) ); // whatever
    }).catch(function (error) {
        res.send( "An error ocurred: " + error ); // handle error
    });
}

FWIW, here's another answer that shows how the same would look like when done properly with Q:

// promisified request
function requestAsync(options) {
    var result = Q.defer();
    request(options, function(error, response, body) {
        if (error) {
            result.reject(error);
        } else {
            result.resolve(body);
        }
    });
    return result.promise;
}

// returns promises for heatmapVolumes
function getHistory(params) {
    return requestAsync({
        method: 'GET',
        url: 'https://api.kaiko.com/v1/charts/' + 
            encodeURIComponent(params.exchange) + '/' + 
            encodeURIComponent(params.pair) +'/history',
        qs: params.qs,
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
    }).then(function (body) {
        return heatmapVolume(body, params.exchange, params.pair);
    }).catch(function (error) {
        // log detailed error and send less revealing message downstream
        console.error('error fetching trades', error);
        throw new Error('Something went wrong while fetching trades');
    });
}

// usage
this.app.all('/api/heatmap', function(req, res) {
    getHistory({
        exchange: "foo", pair: "bar", qs: "qux"
    }).then(function (heatmap) {
        res.send(200, heatmap);
    }).catch(function (error) {
        res.send(500, error);
    });
});

Used Q.deferred and it worked as documented \\o/

function getHistory(params) {
                var deferred = Q.defer();
                var options = {
                    method: 'GET',
                    url: 'https://api.kaiko.com/v1/charts/' + params.exchange + '/' + params.pair +'/history',
                    qs:qs,
                    headers: {
                        "Content-Type": "application/json",
                        "Accept": "application/json"
                    }
                }

                var callback = function(error, response, body) {
                    if(error) {
                        console.log('error fetching trades', error);
                        res.send(500, 'Something went wrong while fetching trades');
                    } else {
                        var body = heatmapVolume(body, params.exchange, params.pair);
                        // console.log("result!", body.exchange, body.pair);
                        result.push(body);
                        // return body;
                        deferred.resolve();
                    }
                }

                request(options, callback);

                return deferred.promise;
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM