13

I'm using a node library which allows simple http requests to be made and returns a promise - this is working nicely, as it allows several to be made in parallel, and I'm then collecting them later with Promise.all(). However, the http request simply returns a string, and I need to know some extra identifying information about each request. So I though one way to do this was to chain something off the request promise and add that information in. This is the code I've got so far showing one such request being added to the array of promises I'll collect later:

var promises = [];
promises.push(new Promise(function(resolve, reject){
    ReqPromise('http://some.domain.com/getresult.php')
    .then(function(reqResult) {
        resolve({
            source: 'identifier',
            value: reqResult
        });
    });
}));

And this is what I get back for this promise when it resolves:

{
    source: 'identifier'
    value: 1.2.3.4
}

Is this the ideal way to 'tag' a promise result? Or is there something about promises I'm misunderstanding which means I don't need to create an extra promise as above? Note that ReqPromise is in an external library and so it's hard to make it take extra parameters and return them.

dsl101
  • 1,715
  • 16
  • 36
  • OK, please ignore question 1 - I thought I was printing the results _inside_ the loop which handles the resolved promises, but turns out I wasn't, and so this was the whole array - which I noticed once I push more than 1 thing into `promises`. My bad. Question 2 still stands though - is this the best way to achieve the desired result? – dsl101 May 18 '16 at 11:21
  • 2
    Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi May 18 '16 at 11:37
  • Please [edit] your question to either show how you were inspecting your result, or to remove the first question from the post. – Bergi May 18 '16 at 11:39
  • You're calling `Promise.all` on the `promises`, you have an array so you're getitng an array. – Benjamin Gruenbaum May 18 '16 at 11:59
  • @Bergi Edited. Tx. – dsl101 May 18 '16 at 15:14

3 Answers3

10

Thanks to @Bergi for the link. This is the code I've ended up with, which I agree is much cleaner. I had tried something like this before, but must have made some mistake, as it was returning undefined to Promise.all(). But now is working nicely without extra promises.

promises.push(ReqPromise('http://some.domain.com/getresult.php').then(function(reqResult) {
    return {
        source: 'identifier',
        value: reqResult
    };
}));
dsl101
  • 1,715
  • 16
  • 36
9

@dsl101, going one step further than your own answer, it can be useful to .map() an array of data to an array of promises, then associate each data item with its corresponding asynchronously-derived result.

For example, you might start with an aray of URLs.

var data = ['http://path/0', 'http://path/1', 'http://path/2', ...];
var promises = data.map(function(url) {
    return ReqPromise(url).then(function(reqResult) {
        return {
            'source': url,
            'value': reqResult
        };
    });
});
Promise.all(promises).then(function(results) {
    // each result has a .value and a corresponding .source (url) property
});
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
1

With async/await syntax introduced in ES8, it's possible to await a promise right inside an object literal

This is @dsl101's answer rewritten to use async/await

promises.push((async function() {
    return {
        source: 'identifier',
        value: await ReqPromise('http://some.domain.com/getresult.php')
    };
})());

And this is @Roamer-1888's

var data = ['http://path/0', 'http://path/1', 'http://path/2', ...];
var promises = data.map(async function(url) {
    return {
        'source': url,
        'value': await ReqPromise(url)
    };
});
var results = await Promise.all(promises)

functions can also be replaced with arrow functions

edit: note that in the pushing promises into array case, the function has to be called first to "become" a promise. in the .map case, the function is called by .map so it has already "become" a promise

Nutchapol
  • 21
  • 6