提问者:小点点

链接promise跨函数Javascript


我怀疑我根本上误解了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个答案

匿名用户

SearchDatabaseForTrack()。then(。。。)不能工作,因为SearchDatabaseForTrack()没有返回承诺,因此您可以返回承诺或使用异步函数。

您可以在for循环中简单地调用DatabaseAPI,而不是递归函数,

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
    });
});

匿名用户

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
});