Javascript кросс-функции обещаний - PullRequest
0 голосов
/ 03 июля 2018

Я подозреваю, что я неправильно понял обещания Javascript, есть идеи?

У меня есть красивая функция, которая запрашивает базу данных, содержащую музыку, которая выглядит следующим образом:

function searchDatabaseForTrack(query,loadedResults){
    loadedResults = loadedResults || [];
    desiredResults = 100;
    if (loadedResults.length < desiredResults) {
        try {
            databaseApi.searchTracks(query, {"offset":loadedResults.length, "limit":"50", }).then(function(data){
                i=0
                if (data.tracks.items.length == 0) {
                    console.log(`Already loaded all ${loadedResults.length} tracks!`)
                    console.log(loadedResults)
                    return loadedResults;
                }
                else {
                    for (thing in data.tracks.items){
                        loadedResults.push(data.tracks.items[i]);
                        i=i+1;
                    }
                    console.log(loadedResults.length, " tracks collected");
                    searchDatabaseForTrack(query,loadedResults)
                }
                });
        } catch(err) {
            console.log("ERROR!", err)
            console.log(loadedResults)
            return loadedResults;
        }
    } else {
        console.log(loadedResults)
        return loadedResults;
    }
}

А потом чуть позже я пытаюсь позвонить и использовать полученные данные.

 function getArtistTracks(artistName){
    searchDatabaseForTrack(artistName).then(function(data){
        console.log(songs);
        songs.sort(function(a,b){
            var c = new Date(a.track.album.release_date);
            var d = new Date(b.track.album.release_date);
            return d-c;
        });
        console.log("songs", songs);
        var newsongs=[];
        i=0
        for (song in songs) {
            newsongs.push(songs[i].track.uri);
            i++
        };
        return newsongs;
    });
}

Я пытаюсь получить вторую функцию "getArtistTracks" для ожидания завершения запроса в первой функции. Теперь я мог бы просто вызвать databaseApi.searchTracks напрямую, но есть ограничение в 50 треков, возвращаемых на результат - что меня смущает.

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

searchDatabaseForTrack().then(...) не должно работать, поскольку searchDatabaseForTrack() не возвращает обещание, поэтому вы можете либо вернуть обещание , либо использовать асинхронную функцию.

вместо рекурсивной функции вы можете просто вызвать databaseApi в цикле for,

desiredResult должен быть аргументом, а не жестко закодированным в функции,

async function searchDatabaseForTrack(query, desiredResults){
    let loadedResults = [], data, currOffset = 0;
    const iterations = Math.ceil(desiredResults / 50);

    for(let n = 0 ; n < iterations; n++){
        cuurOffset = n * 50;
        data = await databaseApi.searchTracks(query, {"offset":currOffset, "limit":"50", });

        if (data.tracks.items.length == 0) {
            console.log(`Already loaded all ${loadedResults.length} tracks!`)
            console.log(loadedResults)
            return loadedResults;
        }
        else {
            loadedResults = loadedResults.concat(data.tracks.items);
            console.log(loadedResults.length, " tracks collected");
        }
    }

    return loadedResults;
}

остальное должно быть в порядке, если вы добавите .catch() для обработки ошибок (как упоминалось в предыдущем ответе), которые автоматически генерируются без необходимости в блоке try/catch:

function getArtistTracks(artistName, 100){
    searchDatabaseForTrack(artistName).then((songs) => {
      // your previous code
    })
    .catch((err) => {
      // handle error
    });
});
0 голосов
/ 04 июля 2018

У searchDatabaseForTrack используйте Promise.all для возврата loadedResults после получения всех результатов. Кроме того, убедитесь, что вы не создаете глобальные переменные неявным образом, как вы делаете с thing. Например, попробуйте что-то вроде этого:

async function searchDatabaseForTrack(query) {
  const desiredResults = 100;
  const trackPromises = Array.from(
    ({ length: Math.ceil(desiredResults / 50) }),
    (_, i) => {
      const offset = i * 50;
      return databaseApi.searchTracks(query, { offset, limit: 50 });
    }
  );
  const itemChunks = await Promise.all(trackPromises);
  const loadedResults = itemChunks.reduce((a, { tracks: { items }}) => (
    [...a, ...items]
  ), []);
  return loadedResults;
};

и

searchDatabaseForTrack(artistName).then((loadedResults) => {
  // do stuff with loadedResults
})
.catch((err) => {
  console.log("ERROR!", err)
  // handle error
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...