Несколько функций обратного вызова с Node Twitter Library - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь отправлять запросы в Twitter с помощью Twitter для узла и сохраняю ответы в массиве для последующей обработки.Я помещаю возвращенные твиты в массив с каждым push(), происходящим в обратном вызове, который, кажется, работает нормально. Моя проблема в том, что у меня проблемы с доступом ко всему массиву со всеми отправленными твитами.

Причина, конечно, в том, что любая попытка работать с этим массивом вызывается до того, какполучены результаты из API Twitter, поэтому я получаю пустой массив.

Как я могу (и я должен) заставить свою функцию, работающую с полным массивом, перейти в другой обратный вызов?Я спрашиваю об этом с точки зрения того, кто все еще пытается получить твердое представление об асинхронном программировании - особенно о множественных обратных вызовах или функциях, которые должны выполняться асинхронно.

Опять же, текущий результат равен tweetHold = [],и я хотел бы, чтобы tweetHold содержал все совпавшие твиты для всех пользователей в searchArray.

let searchArray = {
  users: ['ByBuddha', 'thetweetofgod']
}

let tweetHold = [];  

let T = new Twitter(config);

for (user of searchArray.users) {

  let params = {
    q: 'from:'+ user,
    count: 1,
    tweet_mode: 'extended',
    result_type: 'recent',
    lang: 'en'
  }

  T.get('search/tweets', params, returnedTweets);

}

function returnedTweets(err, tweets, response) {
  tweetHold.push(tweets);
}

// obviously, doesn't work as the array is logged to console before T.get() is done
console.log(tweetHold);

1 Ответ

0 голосов
/ 16 декабря 2018

T.get принимает функцию обратного вызова, которая вызывается после выполнения асинхронной операции.Но так как вы хотите получить несколько ответов, а не только один, использование только обратных вызовов само по себе будет немного грязно.Например, внутри returnedTweets вы можете увеличивать постоянную переменную-счетчик и вызывать следующую функцию один раз counter === searchArray.users.length, но вместо этого было бы более элегантно использовать Promises.

Отобразить каждый T.get вызовPromise, который разрешается с помощью интересующей вас переменной tweets, а затем вызывает Promise.all для массива этих Обещаний.Promise.all принимает массив Promises и возвращает Promise, который разрешается после разрешения каждого Promise в переданном массиве.

Обратите внимание, что похоже, что в данный момент вы игнорируете err, который можетвернитесь из T.get - это, вероятно, не очень хорошая идея, было бы лучше иметь возможность проверить, когда возникают ошибки, а затем каким-то образом обработать ошибку (в противном случае массив tweetHold может иногда содержать поврежденные данные).К счастью, если вы используете Обещания, реализовать это легко - просто reject, если есть err, и catch после Promise.all:

const T = new Twitter(config);
const searchObject = {
  users: ['ByBuddha', 'thetweetofgod']
};

const searchPromises = searchArray.users.map((user) => {
  return new Promise((resolve, reject) => {
    const params = {
      q: 'from:'+ user,
      count: 1,
      tweet_mode: 'extended',
      result_type: 'recent',
      lang: 'en'
    };
    T.get('search/tweets', params, (err, tweets) => {
      if (err) reject(err);
      else resolve(tweets);
    });
  });
});

Promise.all(searchPromises)
  .then((tweetHold) => {
    // tweetHold will be an array containing the `tweets` variable for each user searched
    console.log(tweetHold);
  })
  .catch((err) => {
    // there was an error, best to handle it somehow
    // the `.then` above will not be entered
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...