Chain Promises without using multiple "then's"

I am learning how to use Promises. I have the following functions that return the "i" th xkcd comic name as a promise:

var xkcd = function(i) {
  return new Promise(
    function(resolve, reject) {
      var tempurl = 'https://www.xkcd.com/' + i;
      request(tempurl, function(error, response, body) {
        if (error) reject(error);
        var $ = cheerio.load(body);
        resolve($('title').text() + '\n');
      });
    });
};
Run codeHide result

If I want to get the first 4 names, I bind my .then () as such:

var result = '';
xkcd(1)
  .then(fullfilled => {
    result += fullfilled;
  })
  .then(() => xkcd(2))
  .then(fullfilled => {
    result += fullfilled;
  })
  .then(() => xkcd(3))
  .then(fullfilled => {
    result += fullfilled;
  })
  .then(() => xkcd(4))
  .then(fullfilled => {
    result += fullfilled;
    console.log(result);
  });
Run codeHide result

Is there a more elegant way to do this without tying it a lot? Say, if I want to get the first 50 comic names, I have to chain a lot of β€œthat.”

I can do this without using Promises using recursive callbacks:

function getXKCD(n) {
  var i = 1;
  (function getURL(i){
    var tempurl = 'https://www.xkcd.com/' + i;
    request(tempurl, function(error, response, body) {
      if (error) console.log('error: ' + error);
      var $ = cheerio.load(body);
      //prints the title of the xkcd comic
      console.log($('title').text() + '\n');
      i++;
      if (i <= n) getURL(i);
    });
  })(i);
}

getXKCD(4);
Run codeHide result

But I am interested to know if I can do the same with Promises. Thank.

+4
source share
4 answers

:

function getSequentially(currentArticle, doUntil) {
  if (currentArticle !== doUntil) {
    xkcd(currentArticle)
      .then(article => getSequentially(currentArtile + 1, doUntil))
  }
}

:

Promise
  .all(new Array(AMOUNT_OF_ARTICLES).fill(null).map((nll, i) => xkcd(i + 1)))
  .then(allArticles => ...);

, /, , .

+3

promises , Promise.all, , promises , -

function getXKCD(_start, _end) {
  if (_end >= _start) return Promise.reject('Not valid!');
  var promises = [];

  (function rec(i) {
    var p = new Promise(function(resolve, reject) {
      request('https://www.xkcd.com/' + i, function(error, response, body) {
        if (error !== null) return reject(error);

        if (i <= _end) rec(++i);
        let $ = cheerio.load(body);
        resolve($('title').text());
      });
    });

    promises.push(p);
  })(_start);

  return Promise.all(promises);
}

getXKCD(1, 50).then(res => { /* All done ! */ }).catch( err => { /* fail */ })
+4

. , .map() Promise.all() .reduce(), :

function getXkcd(count) {
  // Make an array of the comic numbers using ES6 Array.fill()...
  var ids = new Array(count).fill(1).map((val, index)=>index+1)

  // Now you can .map() or .reduce() over this list.
}

, . . xkcd , , ...

function getXkcd(max, last) {

    var current = last ? last + 1 : 1;

    xkcd(current)
    .then(function(title) {
        // Process the data.
        result += title;
        // We don't really care about a return value, here.
    })
    .then(getXkcd.bind(null, max, current))
    .catch(function(error) {
        // We should do something to let you know if stopped.
    });
}

. , bind . , : getXkcd(50, 15); .

, :

function getXKCD(max, start) {

    var result = "";

    var getNext = function(id){

        // If we are done, return the result
        if (id > n) {
            return result;
        }

        // Otherwise, keep going.
        return xkcd(id)
        .then(function(title){
            // Accumulate the title in our closure result
            result += title;
            // Send next value
            return id + 1;
        })
        .then(getNext);
    }

    // Kick off the loop
    return getNext(start || 1);
}

getXKCD(50).then(function(results){
    // Do something with the results
}, function(error){
    // Tell us what went wrong
});

getXKCD getNext, Promise. , . bind, " " .

+1

Use async-awaitis the best way, IMO:

   (async () => {
     const result = '';
     for(let i = 1; i < 50; i++) {
       result += await xkcd(i);
     }
     return result
   })().then(result => console.log(result))
0
source

Source: https://habr.com/ru/post/1685202/


All Articles