简体   繁体   中英

Why's this javascript console log printed in this order

This's a snippet from the book Eloquent Javascript (Chapter 11). You can access the sandbox here to try this snippet. I was experimenting with Promises and found that this snippet was printing output in a different order than I was expecting. Instead of the text numbered 1 printed first followed by 2 , I was seeing it the other way. Snippet and Output provided below.

readStorage is called first and then followed by the Promise snippet. Since readStorage is a simple (non-async) loop, I expected its output to be printed first. But weirdly I'm seeing it printed after the output of the callback in then .

Code:

import { bigOak } from "./crow-tech";

bigOak.readStorage("food caches", caches => {
    caches.forEach(firstCache => {
        bigOak.readStorage(firstCache, info => {
            console.log("1:", info);
        });
    });
});


function storage(nest, name) {
    return new Promise(resolve => {
        nest.readStorage(name, result => resolve(result));
    });
}

storage(bigOak, "enemies")
    .then(value => console.log("2: Got", value));

Output:

2: Got ["Farmer Jacques' dog", "The butcher", …]

1: A hollow above the third big branch from the bottom. Several pieces of bread and a pile of acorns.

1: Buried below the patch of nettles (south side). A dead snake.

1: Middle of the hedge at Gilles' garden. Marked with a forked twig. Two bottles of beer.

I don't think it's granted that the 1: logs always happen last, it's just more likely. The readStorage is asynchronous, which means while the storage is loading, other things can occur. And the food caches have another nested load for the food cache detail, leaving plenty of time for the enemies loading to finish. In your case, the order is is better understood if I add more logging:

[food caches] Load cache in the oak
[food caches] Load cache in the meadow
[food caches] Load cache under the hedge
2: Got ["Farmer Jacques' dog", "The butcher", …]
[food caches/ cache in the oak ] A hollow above the third big branch from the bottom. Several pieces of bread and a pile of acorns.
[food caches/ cache in the meadow ] Buried below the patch of nettles (south side). A dead snake.
[food caches/ cache under the hedge ] Middle of the hedge at Gilles' garden. Marked with a forked twig. Two bottles of beer.

Also, it's much clearer when using async/await, see here:

//import { bigOak } from "./crow-tech";
// Funny, if I use async/await, it throws an error regarding the import
// but the code works fine without the import
console.log(bigOak);
bigOak.readStorageAsync = function(name) {
  return new Promise(resolve=>this.readStorage(name, resolve));
};
// load food
const loadFoods = (async() => {
    console.log("[food caches] started");
    const foodCaches = await bigOak.readStorageAsync("food caches")
    for(const foodCache of foodCaches) {
      console.log("[food caches] Load",foodCache);
      const foodInfo = await bigOak.readStorageAsync(foodCache);
      console.log("[food caches/",foodCache,"]", foodInfo);
    }
})();

const loadEnemies = (async() => {
    console.log("[enemies] started");
    const enemies = await bigOak.readStorageAsync("enemies");
    for(const enemy of enemies) {
      console.log("[enemies] Found",enemy);
      //const enemyInfo = await bigOak.readStorageAsync(enemy);
      //console.log("[enemies/",enemy,"]", enemyInfo);
    }
})();

(async() =>{
  await Promise.all([loadFoods, loadEnemies]);
  console.log("All done");
})();

You can now see that the enemy and food loading are separate async operations that act at will. You can also see at he bottom how to wait for them all to finish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM