Desde https://www.learnwithjason.dev/blog/keep-async-await-from-blocking-execution , vi que el primer bloque de código registra valores incorrectos para la publicación, mientras que el segundo bloque de código registra valores correctos.
Funciones de utilidad para versiones correctas e incorrectas
function getBlogPosts() { const posts = [ { id: 1, title: 'Post One', body: 'A blog post!' }, { id: 2, title: 'Post Two', body: 'Another blog post!' }, { id: 3, title: 'Post Three', body: 'A third blog post!' }, ]; return new Promise((resolve) => { setTimeout(() => resolve(posts), 200); }); } function getBlogComments(postId) { const comments = [ { postId: 1, comment: 'Great post!' }, { postId: 2, comment: 'I like it.' }, { postId: 1, comment: 'You make interesting points.' }, { postId: 3, comment: 'Needs more corgis.' }, { postId: 2, comment: 'Nice work!' }, ]; // get comments for the given post const postComments = comments.filter((comment) => comment.postId === postId); return new Promise((resolve) => { setTimeout(() => resolve(postComments), 300); }); }Versión incorrecta La... publicación siempre contiene detalles de la 3.ª publicación, aunque los comentarios son de la publicación 1 y 2.
function loadContent() { getBlogPosts().then((posts) => { for (post of posts) { getBlogComments(post.id).then((comments) => { console.log({ ...post, comments }); }); } }); } loadContent();Versión correcta Los comentarios de las publicaciones 1 y 2 se almacenan correctamente con las publicaciones respectivas
async function loadContent() { const posts = await getBlogPosts(); // instead of awaiting this call, create an array of Promises const promises = posts.map((post) => { return getBlogComments(post.id).then((comments) => { return { ...post, comments }; }); }); // use await on Promise.all so the Promises execute in parallel const postsWithComments = await Promise.all(promises); console.log(postsWithComments); } loadContent();1. La "versión incorrecta" no registra el resultado deseado porque
la variable de post se define como una variable global en lugar de una variable de ámbito de bloque
para cuando then llame a los controladores, la variable de post ya está configurada en la tercera publicación de la matriz. Aquí hay un ejemplo más detallado explicado: https://whistlr.info/2021/async-and-tasks/
Puede verificarlo iniciando sesión después de todo:
function loadContent() { getBlogPosts().then((posts) => { for (post of posts) { getBlogComments(post.id).then((comments) => { console.log({ ...post, comments }); }); } }); } loadContent(); console.log(post);Esto debería arrojar en modo estricto .
2. La solución sería usar let/const en lugar de la declaración de variable post , por ejemplo:
function loadContent() { getBlogPosts().then((posts) => { // Use block-scoped let to avoid the variable // leaking to the global scope for (let post of posts) { getBlogComments(post.id).then((comments) => { console.log({ ...post, comments }); }); } }); } loadContent(); Tenga en cuenta que incluso en el modo estricto, el uso del modificador var no ayudará, ya que está limitado al alcance de la función adjunta, no a un alcance de bloque en comparación con let/const . Más contexto aquí: https://javascript.info/var