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

139
Views
Asynchronous call stack execution gap

I am reading "Eloquent JavaScript" and at the end of Asynchronous chapter there is a section about execution gap in asynchronous operations and it shows an example. The example code below from the book is not runable as it uses some made up scenario.

function anyStorage(nest, source, name) {
   if (source == nest.name) return storage(nest, name); else return routeRequest(nest, source, "storage", name);
}

async function chicks(nest, year) {
   let list = "";
   await Promise.all(network(nest).map(async name => {
     list += `${name}: ${
     await anyStorage(nest, name, `chicks in ${year}`)
   }\n`; }));
   return list;
 }

It says the problem with this code, as I understand, is each asynchronous call e.g. anyStorage will actually concatenate an empty list and can't see the mutation from other asynchronous calls.

I tried to replicate this problem as below:

function delay(n) {
    return Promise.resolve(setTimeout(()=>{}, n*1000));
}

async function asyncSum(a) {
    let sum = 0;
    await Promise.all(a.map(async i => sum += await delay(i)));
    return sum;
}

asyncSum([1,2,3,4]).then(value => console.log(value));

But this works as expected. It prints the sum correctly. So did I misunderstand the book or there is something wrong with my example?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

The problem in the original code is that here:

list += `${name}: ${ await ...

The list += is like doing list = list + - but the second list:

list = list +
       ^^^^

refers to the list at that moment - before any of the asynchronous calls have completed. Eventually one of them will complete and assigns to list. But once the next one resolves, because the list it has refers to the original one, not the newly updated one, the prior results will be lost.

Here's a demo:

const getMultipliedNum = num => Promise.resolve(num * 3);

(async() => {
  let list = "";
  await Promise.all([1, 2, 3].map(async num => {
    list += `${num}: ${ await getMultipliedNum(num)}\n`;
  }));
  console.log(list);
})();

Your example has the same issue, though the delay function is broken - the result is 4, which is only the result of the final setTimeout call (because setTimeout returns the timeout ID). Fixing it to demonstrate the problem:

function delay(n) {
    return Promise.resolve(n);
}

async function asyncSum(a) {
    let sum = 0;
    await Promise.all(a.map(async i => sum += await delay(i)));
    return sum;
}

asyncSum([1,2,3,4]).then(value => console.log(value));

The result is 4, rather than 10 - this demonstrates that sum += await somethingElse inside a parallel loop doesn't work.

Another way of looking at it:

sum += await somethingElse

is like doing

const currentValueOfSum = sum;
sum = currentValueOfSum + await somethingElse;
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!