Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

380
Views
How do lexical environments work with promises?

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.
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

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

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!