Pari Baker
Pari Baker

Reputation: 716

resolving cursors with promises

I am trying to query the Twitter API for users' followers to compare the two. I am using a cursor to retrieve the list of users. I set it up using promises, where the first get request gets the users followers to a limit, then looks for the cursor passes the data into an array and then resolves with the value of the cursor into a the same recurring function until the cursor returns 0, when that happens I want to send it all in a res. When I set up my initial promises and use promise.all to resolve them and attach a .then, the promise. all resolves first. I've tried resolving the promise from the recurring function and then returning another promise to the first function but I can't seem to get it to work. Any ideas?

const express = require("express");
const router = express.Router();
const twitter = require("../controllers/twitter");

let object1 = {
  params: {
    screen_name: "xxxx",
    count: "40"
  }
};
let object = {
  params: {
    screen_name: "xxxxx",
    count: "40"
  }
};
let data = [];
router.get("", (req, res, next) => {
  let one = getUserFollowers("/1.1/followers/ids.json", object);
  let two = getUserFollowers("/1.1/followers/ids.json", object1);
  Promise.all([one, two]).then(console.log);
});

function getUserFollowers(uri, parameters) {
  twitter
    .get(uri, parameters)
    .then(resp => {
      let ids = resp.data.ids;
      data.push(...ids);

      return recurr(resp, uri, parameters);
    })
    .then(data => {
    //if instead I re console.log the data I can get it, but I need to resolve it back in the router so I can send it as a res. 
      return new Promise((resolve, reject) => {
        resolve(data);
        reject(error);
      });
    });
}

let recurr = (response, uri, params) => {
  if (response.data.next_cursor > 0) {
    params.params.cursor = response.data.next_cursor;
    return getUserFollowers(uri, params);
  } else {
    return Promise.resolve(data);
  }
};

module.exports = router;

Upvotes: 0

Views: 515

Answers (1)

Bravo
Bravo

Reputation: 6264

The mistakes in your code:

getUserFollowers doesn't return anything - so, lets add a return before twitter.get

.then(data => {
//if instead I re console.log the data I can get it, but I need to resolve it back in the router so I can send it as a res. 
  return new Promise((resolve, reject) => {
    resolve(data);
    reject(error);
  });
});

This makes no sense for several reasons.

  1. you can only "complete" a Promise once, so having resolve followed by reject means only resolve is executed ...
  2. .then always returns a promise, so there's usually no need for a Promise constructor when the .then contains only synchronous code; and
  3. what you're actually doing is a no-op ... you've received data in .then, done nothing to it, and in a complicated way, returned data out the other end

Since recurr is only ever called inside a .then you don't need to guarantee you're returning a Promise using Promise.resolve - however, I'd lose the recurr function altogether, it just complicates things in such simple code

he fact that you have one global data variable that has data pushed by both getUserFollowers will probably cause you problems too

Rewriting to fix all of the above, you get:

const express = require("express");
const router = express.Router();
const twitter = require("../controllers/twitter");

let object1 = {
  params: {
    screen_name: "xxxx",
    count: "40"
  }
};
let object = {
  params: {
    screen_name: "xxxxx",
    count: "40"
  }
};

router.get("", (req, res, next) => {
    let one = getUserFollowers("/1.1/followers/ids.json", object, []);
    let two = getUserFollowers("/1.1/followers/ids.json", object1, []);
    Promise.all([one, two]).then(console.log);
});

function getUserFollowers(uri, parameters, data) {
    return twitter
    .get(uri, parameters)
    .then(resp => {
        let ids = resp.data.ids;
        data.push(...ids);
        if (resp.data.next_cursor > 0) {
            params.params.cursor = response.data.next_cursor;
            return getUserFollowers(uri, params, data);
        }
        return data;
    });
}

module.exports = router;

Upvotes: 1

Related Questions