skip to Main Content

I am trying to use Twitter’s API with node.js using async/await (which I admit I am new to) but I am struggling to get to the next cursor value.

Why does my getFollowers function bellow always returns before the await block?

require('dotenv').config();

const Twitter = require('twitter');
 
const client = new Twitter({
  consumer_key: process.env.API_KEY,
  consumer_secret: process.env.API_KEY_SECRET,
  access_token_key: process.env.ACCESS_TOKEN,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET
});
 
const getFollowers = async (screen_name, count, cursor) => {
    console.log("Cursor: " + cursor);
    const params = {
        screen_name: screen_name,
        count: count,
        cursor: cursor
    };

    const promise = await client.get('followers/list', params)
        .then(data => {
            console.log("This promise is never executed...");
            return data.next_cursor;
        })
        .catch(err => console.error(err));

    return promise;
}

const main = async () => {
    let cursor = -1;
    while (cursor != 0) {
        getFollowers(process.env.SCREEN_NAME, 200, cursor)
            .then(next_cursor => {
                cursor = next_cursor;
                console.log("This promise is never executed either... " + cursor);
            });
    }
}

main();

2

Answers


  1. Chosen as BEST ANSWER

    I gave up on the implementation using the Twitter package and switched to using axios instead.

    require('dotenv').config();
    
    const axios = require('axios');
    
    const credentials = {
        consumer_key: process.env.API_KEY,
        consumer_secret: process.env.API_KEY_SECRET,
        access_token_key: process.env.ACCESS_TOKEN,
        access_token_secret: process.env.ACCESS_TOKEN_SECRET
    };
    
    const FOLLOWERS_LIST_ENDPOINT = "https://api.twitter.com/1.1/followers/list.json";
    
    //documentation: https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only
    const generateToken = async () => {
        return process.env.BEARER_TOKEN;
    }
    
    //documentation: https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/follow-search-get-users/api-reference/get-followers-list
    const getFollowers = async (screen_name, count, cursor) => {
        let token = await generateToken();
        let requestConfig = {
            params: {
                screen_name: screen_name,
                count: count,
                cursor: cursor,
                include_user_entities: false
            },
            headers: { 
                Authorization: `Bearer ${token}` 
            }
        };
        let response = await axios.get(FOLLOWERS_LIST_ENDPOINT, requestConfig);
        let users = response.data.users;
        processUsers(users);
        return response.data.next_cursor;
    };
    
    const processUsers = (users) => {
        users.map(user => {
            console.log(user.screen_name);
        });
    }
    const main = async () => {
        let cursor = -1;
        while (cursor != 0) {
            cursor = await getFollowers(process.env.SCREEN_NAME, 200, cursor);
        }
    }
    
    main();
    

  2. With your .then statement in main(), you weren’t awaiting for client.get() to resolve, but for data.next_cursor(). Therefore, promise of client.get() remained pending.

    Instead, return the promise of client.get() as a in getFollowers(). This will make sure that when you call getFollowers().then() in main(), you are referring to client.get.

    Edit:

    Following the line of thought in the answer in this question, I have modified getFollowers(). It now includes a promise that is resolved when cursor hits the value of 0. Every other value, a request will be made.

    I have a concern though with the rate limit of requests, which is set to 15 per 15 minutes. Since a new request is made for every non 0 next_cursor value, you’ll reach this limit quite soon for accounts with many followers.

    Also note that the data retrieved will be stored in an array. I am not sure what your use case exactly is.

    const Twitter = require('twitter');
    
    const client = new Twitter({
        consumer_key: '',
        consumer_secret: '',
        bearer_token: ''
    });
    
    let output = [];
    
    const getFollowers = (screen_name, count) => {
        let cursor = -1;
    
        const params = {
            screen_name: screen_name,
            count: count,
            cursor: cursor
        };
    
        return new Promise((resolve, reject) => {
            client.get('followers/list', params, function getData(err, data, response) {
                if (err) reject(response.body);
                output.push(data);
                cursor = data.next_cursor;
                
                if (cursor > 0) {
                    client.get('followers/list', params, getData);
                }
                if (cursor = 0) {
                    resolve('done');
                }
            });    
        });
    };
    
    const main = async () => {
       await getFollowers('MozDevNet', 200);
       console.log(output);
    
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search