链接承诺跨功能Javascript

时间:2018-07-03 20:47:13

标签: javascript database promise

我怀疑我从根本上误解了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 :(得分:0)

searchDatabaseForTrack().then(...)不起作用,因为searchDatabaseForTrack()不返回承诺,因此您可以return a promise或使用async函数。

代替递归函数,您只需在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
    });
});

答案 1 :(得分:-1)

获取所有结果后,请incRow < numLines - 1使用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;
};