Как go добавить асинхронную информацию в глобальный массив? - PullRequest
0 голосов
/ 14 марта 2020

Я изучаю Node JS, а также как получить доступ к информации API, и я столкнулся с проблемой, когда при извлечении значений sh в массив информация никогда не добавляется глобально.

Допустим, у меня есть var albIds= new Array(5), значения никогда не добавляются. Посмотрев на this и this , я теперь знаю, что проблема в том, что информация никогда не попадает в массив к тому времени, когда я его вызываю, однако синхронный код выполняется первым, однако Я запутался в том, как заставить синхронное ожидание завершения асинхронного.

мой код.

//prints out albums 1-5 id's
var id = '3TVXtAsR1Inumwj472S9r4';
var albIds= new Array(5);
async function getAlbums(i) {

var authOptions = {
  url: 'https://accounts.spotify.com/api/token',
  headers: {
    'Authorization': 'Basic ' + (new Buffer.from(client_id + ':' + client_secret).toString('base64'))
  },
  form: {
    grant_type: 'client_credentials'
  },
  json: true
};

request.post(authOptions, function(error, response, body) {
  if (!error && response.statusCode === 200) {

    // use the access token to access the Spotify Web API
    // const querystring = require('querystring');

const data = {
  market: "US",
  limit: "5"
};
const  q = querystring.stringify(data);
    var token = body.access_token;
    var options = {
      url: 'https://api.spotify.com/v1/artists/'+id+'/albums?'+q,
      headers: {
        'Authorization': 'Bearer ' + token
      },
      json: true
    };
  request.get(options, function(error, response, body)
     {
  for(var i = 0; i<5;i++)
      {
       albIds.push(body.items[i].id);
      }
});
}

})
};

async function fetchUsers()
{
  for(var i = 0;i<5;i++)
  {
    await getAlbums(i);
    console.log(albIds[i]);
  }
}
fetchUsers();

Любая помощь приветствуется. Для справки я использую API Spotify

1 Ответ

1 голос
/ 14 марта 2020

К вашему сведению, albIds НЕ является глобальным. Это переменная области действия модуля.

Затем вам нужно понять, что await ТОЛЬКО делает что-то полезное, если вы ожидаете обещание, связанное с завершением асинхронной операции. Это НЕ относится к вашей функции getAlbums(). Хотя оно объявлено async и возвращает обещание, оно не связано вообще с завершением асинхронных операций.

Вместо этого обещание выполняется задолго до того, как вы поместили какие-либо данные в массив albIds. Таким образом, вы думаете, что массив пуст (потому что когда вы пытаетесь его использовать, в него еще ничего не вставлено).

Вот мое предложение:

const rp = require('request-promise');

//prints out albums 1-5 id's
const id = '3TVXtAsR1Inumwj472S9r4';

async function getAlbums(i) {
    const albIds = new Array(5);

    const authOptions = {
        url: 'https://accounts.spotify.com/api/token',
        headers: {'Authorization': 'Basic ' + (new Buffer.from(client_id + ':' + client_secret).toString('base64'))},
        form: {grant_type: 'client_credentials'},
        json: true
    };

    const body = await rp.post(authOptions, function(error, response, body) {

    const data = {
        market: "US",
        limit: "5"
    };
    const q = querystring.stringify(data);
    const token = body.access_token;
    const options = {
        url: 'https://api.spotify.com/v1/artists/' + id + '/albums?' + q,
        headers: { 'Authorization': 'Bearer ' + token },
        json: true
    };
    let result = await rp.get(options);

    for (let j = 0; j < 5; j++) {
        albIds.push(result.items[j].id);
    }
    // let resolved value be the array
    return albIds;
};

async function fetchUsers() {
    for (let i = 0; i < 5; i++) {
        const albiIds = await getAlbums(i);
        console.log(albIds[i]);
    }
}
fetchUsers();

Сводка изменений:

  1. Переключиться на библиотеку запросов-обещаний, которая использует обещания для автоматической передачи результатов и проверки статуса 2xx. Это гораздо более совместимо с функцией async, и мы можем использовать с ней await.
  2. Сделать albIds разрешенным значением getAlbums(), а не общей переменной с большей областью действия (намного более невосприимчив к проблемам параллелизма и гарантирует, что вы не сможете использовать его до того, как он будет готов.
  3. В fetchUsers() используйте albIds, полученное из обещания, возвращенного getAlbums().
  4. Измените все переменные на let или const, в зависимости от ситуации (здесь вообще не нужно использовать var).
  5. Используйте await при вызовах запроса-обещания для упрощения кода и быть совместимым с обещанием, что getAlbums() возвращается.

FYI, если это довольно новый код, я бы прекратил использовать библиотеки request или request-promise как они официально устарели для новых разработок. Хотя они будут поддерживаться, они не будут получать новые функции, добавленные к ним со временем. Вы можете прочитать, почему это происходит, но в основном они существовали так долго, и node.js изменилось так сильно за это время, что они стали чем-то вроде беспорядка, чтобы поддерживать и двигаться вперед. Но есть так много пользователей, что они не могут по-настоящему вносить критические изменения в API, что они должны были бы сделать, чтобы действительно продолжать его продвигать (например, сделать его полностью ориентированным на обещания). И, поскольку есть ряд хороших альтернатив, имеющих более современный дизайн, они решили перевернуть будущее на другие альтернативы. Я лично использую got() для большинства своих применений, но есть множество других вариантов на выбор.

См. Должен ли я использовать модуль 'request' для нового проекта? для получения дополнительной информации.

...