-3

I would like to return not only the result of this Promise but also the iterable, the url, with which it was a called. urls is an array of urls.

function findMainLink(urls) {
  return Promise.all(urls.map((url) => {
  var result = nightmare
    .goto(url)
    .wait('#main')
    .evaluate(function() {
       return document.querySelector('#main a').href;
    });

    nightmare.end()
    return result
  }
}

vo(findMainLink)([
 'https://yahoo.com',
 'https://google.com'
])
.then(res => console.log(res))
.catch(e => console.error(e))

when I do return {result,url} it does not resolve but instead gives me back the current status of the promise. How would I include the url in the result?

warg
  • 41
  • 4
  • I am handling promises from the npm package nightmare and I want to visit websites at the same time, hence the promises. I want to include the url with which the nightmare function is called – warg Jul 06 '16 at 18:02
  • And that has...what exactly to do with the code you posted? – Jared Smith Jul 06 '16 at 18:16
  • You really should show us your actual code, not some simplified example that barely matches it. – Bergi Jul 06 '16 at 18:17
  • @torazaburo Calling `Promise.all()` on an array of non-promises is actually possible. It behaves like calling it on an array of promises, except that it resolves without delay. – Tomalak Jul 06 '16 at 18:20
  • I have updated the example to include my code. I don't understand why I am showered by downvotes :( – warg Jul 06 '16 at 18:21
  • `return {result,url}` provide an example with the output. – Kevin B Jul 06 '16 at 18:24
  • so I cannot return an object from a Promise but an array? – warg Jul 06 '16 at 18:24
  • You can, it should work. note however that if `result` is a promise, then you're no longer returning a promise and instead are returning an object that has a promise and your .then will run before any of them resolve.. You returned an object, not a promise, and therefore it's giving you an object, not the result of the promise. – Kevin B Jul 06 '16 at 18:24

1 Answers1

2

What you want is

function findMainLink(urls) {
  return Promise.all(urls.map((url) => {
    var result = nightmare
      .goto(url)
      .wait('#main')
      .evaluate(function() {
         return document.querySelector('#main a').href;
      });

    nightmare.end();
    return result;
  })
    .then(results => results.map((result, i) => ({result, url[i]}));
}

Passing an array of tuples to Promise.all of course won't work, since a tuple is not a promise and Promise.all has no way to know it's supposed to look inside the tuple. Instead, the code above waits for all the promises to resolve then maps the results to give you your array of tuples (and returns a promise for that).

  • hmm, yeah that would work. I was thinking doing `return result.then( result => {result, url} )` but both would have the same result. – Kevin B Jul 06 '16 at 18:36
  • Either is OK, yours might be a little bit cleaner. Minor syntax note, needs to be `result => ({result, url})`. –  Jul 06 '16 at 18:38