如何解决以下哪个代码是在JavaScript中使用Promises的正确方法?
因此,我认为这更多的是讨论而不是问题。我当时与Promises一起工作,并且我的代码可以完全正常工作,并且一切正常,但是后来我遇到了另一种实现相同结果的方法,但是我觉得这种方法不是使用Promises的最佳方法。因此,我想讨论如何有效地使用Promises。
因此,我想做的是使用pokeapi
获取不同口袋妖怪的数据,然后按它们出现的顺序显示它们的名称和类型。 (注意:重要的是,顺序不要中断。)
我先fetch
https://pokeapi.co/api/v2/pokemon?limit=150
这个URL,然后.json()
响应,然后这个json包含一个数组results
,该数组依次包含每个口袋妖怪的URL。现在,我使用Promise.all()
来获取所有这些URL,然后再次使用Promise.all()
将这些响应转换为json。 注意:我使用Promise.all()两次很重要,因为第二种方法只使用一次,这让我感到困扰。
所以,这是我编写的代码
const container = document.querySelector(".container");
fetch('https://pokeapi.co/api/v2/pokemon?limit=150')
.then(response => response.json())
.then(json => {
const responseArr = [];
json.results.forEach(el => {
responseArr.push(fetch(el.url));
});
return Promise.all(responseArr);
})
.then(responses => {
const jsonArr = [];
responses.forEach(el => {
jsonArr.push(el.json());
});
return Promise.all(jsonArr);
})
.then(jsons => {
jsons.forEach((json,index) => {
const pokemonName = json.name;
const pokemonType = json.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemonType} <br>`;
});
})
<div class="container"></div>
这是第二种方法
const container = document.querySelector(".container");
fetch('https://pokeapi.co/api/v2/pokemon?limit=150')
.then(response => response.json(),e => {
console.error(e);
throw e;
})
.then(json => {
Promise.all(json.results.map(el => fetch(el.url)))
.then(arr => {
arr.map(response => response.json())
.forEach((result,index) => {
result.then(el => {
const pokemonName = el.name;
const pokemontype = el.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemontype} <br>`;
})
})
}).catch(e => {
console.error(e)
throw e;
});
}).catch(e => {
console.error(e)
throw e;
});
<div class="container"></div>
在第二种解决方案中,这部分困扰着我。
arr.map(response => response.json())
.forEach((result,index) => {
result.then(el => {
const pokemonName = el.name;
const pokemontype = el.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemontype} <br>`;
})
})
因为response.json()
也将返回promise,因此也应正确链接,这里首先满足.json()
的人将首先添加到内部HTML中,因此列出宠物小精灵的顺序可能感到不安。
此外,我在编写此代码时发现了一些奇怪的东西,如果api端点更改为https://pokeapi.co/api/v2/pokemon?limit=15
,即仅请求15个神奇宝贝,那么每次执行代码时,第二种方法的顺序都会受到干扰,但令人惊讶的是要求获得150只神奇宝贝时保持原样。
解决方法
所以列出宠物小精灵的顺序可能会受到干扰。
是的。如果此方法已损坏,请不要使用。
但是,这并不意味着您需要两次使用Promise.all
。与其先等待所有响应然后再等待所有响应主体,不如为数组中的每个项目创建一个单独的Promise链,然后立即等待所有最终结果:
const container = document.querySelector(".container");
fetch('https://pokeapi.co/api/v2/pokemon?limit=150')
.then(response => response.json())
.then(json => {
const jsonPromises = json.results.map(el => {
return fetch(el.url).then(response => response.json());
});
return Promise.all(jsonPromises);
})
.then(arr => {
for (const [index,json] of arr.entries()) {
const pokemonName = json.name;
const pokemonType = json.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemonType} <br>`;
});
})
,
下面的解决方案如何尽快打印口袋妖怪并同时保持顺序呢?
const container = document.querySelector(".container");
async function fetchPokemons(){
const response = await fetch('https://pokeapi.co/api/v2/pokemon?limit=150');
const {results} = await response.json();
const promises = results.map(async (result,index) => {
const {url} = result;
const pokemon = await (await fetch(url)).json();
await Promise.all(promises.slice(0,index));
const pokemonName = pokemon.name;
const pokemontype = pokemon.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemontype} <br>`;
return;
});
return Promise.all(promises);
}
fetchPokemons();
<div class="container"></div>
,
为便于记录,我建议使用TTY112358的解决方案。但是要回答您最初的问题,这与性能无关:
除了其他方面,还设计了承诺,因此您可以避免在第二个示例中嵌套。所以,是的,第一个版本更“正确”,或者更准确地说,第二个版本同样正确,但丑陋,写成不良样式。
顺便说一句,可以通过使用map
来简化第一个示例,就像这样,您会发现async/await
不一定优于编写良好的then
链s –实际上取决于逻辑是否确实是一个链,以及是否具有可以在其中使用的即用型功能:
fetch('https://pokeapi.co/api/v2/pokemon?limit=150')
.then(response => response.json())
.then({results} => Promise.all(results.map(el => fetch(el.url))))
.then(responses => Promise.all(responses.map(el => el.json()))
.then(jsons => {
jsons.forEach((json,index) => {
const pokemonName = json.name;
const pokemonType = json.types[0].type.name;
container.innerHTML += `(${index+1}) ${pokemonName} - ${pokemonType} <br>`;
});
})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。