词汇环境如何处理承诺?

发布于 2025-02-06 14:35:03 字数 2122 浏览 0 评论 0 原文

来自, 我看到了帖子的第一个块代码日志错误值,而代码日志的第二个块正确值。

实用程序的功能是错误和正确版本的功能

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

错误版本 ...帖子总是包含第三帖的详细信息,即使评论来自帖子1和2

function loadContent() {
  getBlogPosts().then((posts) => {
    for (post of posts) {
      getBlogComments(post.id).then((comments) => {
        console.log({ ...post, comments });
      });
    }
  });
}

loadContent();

正确的版本 post 1和2的评论分别与帖子合适地存储在一起,

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. 为什么错误的版本不log log循环变量的正确帖子?理想情况下,解释可以集中于词汇环境如何与承诺一起工作,假设与此错误相关,
  2. 是否可以在没有地图的情况下修复错误的版本? 也许出于某种原因,我无法并行运行,地图 + Promise.All模式都可以。

From https://www.learnwithjason.dev/blog/keep-async-await-from-blocking-execution,
I saw the 1st block of code log wrong values for post, while 2nd block of code logs correct values.

Utility Functions for both wrong and right versions

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

Wrong version
The ...post always contains details from the 3rd post, even though comments are from post 1 and 2

function loadContent() {
  getBlogPosts().then((posts) => {
    for (post of posts) {
      getBlogComments(post.id).then((comments) => {
        console.log({ ...post, comments });
      });
    }
  });
}

loadContent();

Correct version Comments from post 1 and 2 are correctly stored with respectively posts

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. Why does the wrong version not log the correct post from the looping variable? Ideally the explanation can focus on how lexical environments work with Promises, assuming that's relevant to this bug
  2. Is there a way to fix the wrong version without map?
    Maybe for some reason I cannot have things run in parallel, which the map + Promise.all pattern does.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放我走吧 2025-02-13 14:35:03

1。“错误的版本”未记录所需的结果,因为

您可以通过记录帖子来验证它:

function loadContent() {
  getBlogPosts().then((posts) => {
    for (post of posts) {
      getBlogComments(post.id).then((comments) => {
        console.log({ ...post, comments });
      });
    }
  });
}

loadContent();
console.log(post);

这应该插入严格模式

2。修复将是使用 Let/const 代替 post 变量声明:

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

请注意,即使在严格的模式下,也使用 var var modifier不会有帮助,因为它范围范围 Let/const 相比,封闭功能范围不是块范围。
此处的更多上下文: https://javascript.info/var

1. The "wrong version" does not log the desired result because

  • the post variable is defined as a global variable rather a block-scoped variable

  • by the time then handlers get called the post variable is already set to the third post from the array. Here is a more detailed example explained: https://whistlr.info/2021/async-and-tasks/

You can verify it by logging post after all:

function loadContent() {
  getBlogPosts().then((posts) => {
    for (post of posts) {
      getBlogComments(post.id).then((comments) => {
        console.log({ ...post, comments });
      });
    }
  });
}

loadContent();
console.log(post);

This should throw in strict mode.

2. The fix would be to use let/const in place of the post variable declaration e.g.:

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

Note that even in strict mode using var modifier won't help as it is scoped to the enclosing function scope not a block scope compared to let/const.
More context here: https://javascript.info/var

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文