Как выполнить обещание после нескольких запросов API? - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь создать обещание с помощью зацикленного запроса API к Spotify. Spotify работает так, что я могу получать только 100 треков за раз, поэтому я проверяю, есть ли еще треки, и повторно запускаю функцию, пока все треки не будут добавлены в список «элементов». Прямо сейчас обещание разрешается после 1 запроса, но мне нужно разрешить после того, как все запросы сделаны. Мой код:

function getItems(myUrl) {
  return new Promise((resolve, reject) => {
    let items = []
    request.post(authOptions, function(error, response, body) {
      if (!error && response.statusCode === 200) {

        // use the access token to access the Spotify Web API
        var token = body.access_token;
        var options = {
          url: myUrl,
          headers: {
            'Authorization': 'Bearer ' + token
          },
          json: true
        };
        request.get(options, function(error, response, body) {
          if (error) return reject(error);

          for (var item of body['items']) {
            items.push(item)
          }
          if (response.body.next != null) {
            getItems(response.body.next)
          }
          resolve(items)
        })
      } else {
        reject(error)
      }
    })
    return items
  })
}

getItems('https://api.spotify.com/v1/playlists/1vZFw9hhUFzRugOqYQh7KK/tracks?offset=0')
  .then(res => console.log(res))

Ответы [ 3 ]

0 голосов
/ 17 июня 2020

Я немного изменил его, чтобы иметь возможность разрешить обещание после того, как все запросы будут выполнены; однако, когда я console.log элементы, ничего не возвращается.

let items = []

function getItems(myUrl) {
  return new Promise((resolve, reject) => {
    request.post(authOptions, function(error, response, body) {
      if (!error && response.statusCode === 200) {

        // use the access token to access the Spotify Web API
        var token = body.access_token;
        var options = {
          url: myUrl,
          headers: {
            'Authorization': 'Bearer ' + token
          },
          json: true
        };
        request.get(options, function(error, response, body) {
          if (error) return reject(error);

          for (var item of body['items']) {
            items.push(item)
          }
          if (response.body.next != null) {
            getItems(response.body.next)
          } else {
            resolve(items)
          }
        })
      } else {
        reject(error)
      }
    })
  })
}

getItems('https://api.spotify.com/v1/playlists/1vZFw9hhUFzRugOqYQh7KK/tracks?offset=0')
  .then(console.log(items))
0 голосов
/ 17 июня 2020

Попробуйте использовать async / await. Я не смог отладить свой код, потому что у меня нет доступа к Spotify. Но я надеюсь, что это поможет вам понять идею.

async function getItems(url) {
    var items = [];
    
    async function getData(url, items) {
        return new Promise((resolve, reject) => {
            request.post(authOptions, function(error, response, body) {
                if (error || response.statusCode !== 200) reject(error);

                var token = body.access_token;
                var options = {
                    url: url,
                    headers: {
                        'Authorization': 'Bearer ' + token
                    },
                    json: true
                };
                request.get(options, function(error, response, body) {
                    if (error) return reject(error);

                    for (var item of body['items']) {
                        items.push(item)
                    }
                    if (response.body.next == null) {
                        resolve([items, null])
                    } else {
                        resolve([items, response.body.next])
                    }
                })
            })
        })
    }

    while (url) {
        var response = await getData(url, items);
        items = response[0];
        url = response[1];
    }

    return items;
}


const myUrl = 'https://api.spotify.com/v1/playlists/1vZFw9hhUFzRugOqYQh7KK/tracks?offset=0';
async function main() {
    const items = await getItems(myUrl);
    console.log('Result: ' + items)
}


main();
0 голосов
/ 16 июня 2020

Сделайте что-нибудь вроде

function getItems(myUrl, offset=0, items=[]) {
  return new Promise((resolve, reject) => {
request.post(authOptions, function(error, response, body) {
  if (!error && response.statusCode === 200) {

    // use the access token to access the Spotify Web API
    var token = body.access_token;
    var options = {
      url: myUrl,
      headers: {
        'Authorization': 'Bearer ' + token
      },
      json: true
    };
    request.get(options, function(error, response, body) {
      if (error) return reject(error);

      items = items.concat(body.item);
      offset++;

      if (response.body.next != null) {
         return resolve(getItems(response.body.next), offset, items)
      } else {
        return resolve(items)
      }
    })
  } else {
    reject(error)
  }
})
  })
}

getItems('https://api.spotify.com/v1/playlists/1vZFw9hhUFzRugOqYQh7KK/tracks?offset=0')
  .then(console.log(items))

Это работает так: одна и та же функция рекурсивно вызывается для получения дополнительных элементов из Spotify и просто добавляет к ранее возвращенным элементам

...