如何解决“刚刚评估了以下值。”对于链式 then 函数

How to resolve “Value below was evaluated just now.” for chained then functions

我正在使用 https://pokeapi.co/ API 来获取所有口袋妖怪。我正在尝试遍历每个宠物小精灵列表 https://pokeapi.co/api/v2/pokemon/?limit=44 并获取数据。我正在为此使用承诺。但我的承诺正在回报我“Value below was evaluated just now”.

我已经尝试过解决方法:-

1. JSON.stringify().
2. JSON.parse(JSON.stringify())
3. setTimeout
4. map, concat etc.

var getPokemonList = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "https://pokeapi.co/api/v2/pokemon/?limit=4");
    xhr.onload = () => resolve(JSON.parse(xhr.responseText));
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
});

var getPokemonListDetails = getPokemonList
    .then(function (fulfilledList) {
        console.log(fulfilledList.results);
        var pokemonList = [];
        setTimeout(() => {
            fulfilledList.results.forEach(function (pokemon) {
                const xhr = new XMLHttpRequest();
                xhr.open("GET", pokemon.url);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        pokemonList.push(JSON.parse(xhr.responseText));
                    }
                };
                xhr.send();
            });
        }, 3000); 
        return pokemonList;
    })
    .then(function (fulfilledListDetails) {
        console.log(fulfilledListDetails);
    })
    .catch(function (error) {
        console.log(error.message);
    });

上面的代码给了我“下面的值刚刚计算过”数组数据。我可以做些什么来让它可用。

function getPokemonList(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "https://pokeapi.co/api/v2/pokemon/?limit=4");
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  }).then(function(data){
    //Do whatever with data
}).catch(function(error){
    //Handle error
});

来源:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

您正确地使用了 Pomise 来包装第一个 API 调用,但是您没有包装计时器和其他 API 调用,因此承诺在它们完成之前解析。 现代浏览器支持 fetch(),这比 XMLHttpRequest 更容易使用,而且它已经 returns 一个可以轻松链接的 Promise。现在唯一剩下的就是包装超时:

 const delay = ms => new Promise(res => setTimeout(res, ms));

现在我们有了所有这些 Promise,Promise.all 可以使用链接来组合它们:

 const pokemonList = fetch(  "https://pokeapi.co/api/v2/pokemon/?limit=4" ).then(res => res.json());

 const pokemonDetails = pokemonList.then(list => {
   return delay(3000).then(() => {
     return Promise.all(list.results.map(pokemon => {
       return fetch(pokemon.url).then(res => res.json());
    });
  });
 });