为什么此javascript控制台日志按此顺序打印

时间:2019-08-02 10:46:13

标签: javascript

这是《 Eloquent Javascript》(第11章)一书的摘录。您可以访问沙盒here来尝试使用此代码段。 我正在试验Promises,发现此代码段的打印输出顺序与我预期的顺序不同。我不是先打印编号为1的文本,而是先打印2,而是用另一种方式看到它。下面提供了代码段和输出。

首先调用

readStorage,然后调用Promise片段。由于readStorage是一个简单的(非异步)循环,因此我希望其输出先打印出来。但是很奇怪,我看到它在then中的回调输出之后打印出来。

代码:

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

输出:

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.

1 个答案:

答案 0 :(得分:0)

我不认为1:日志总是最后出现是认可的,这更有可能。 readStorage是异步的,这意味着在加载存储时,可能会发生其他事情。而且食物储藏室还为食物储藏室的细节提供了另一个嵌套的负载,从而使敌人有足够的时间完成装载。在您的情况下,如果我添加更多日志记录,则会更好地理解该顺序:

[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.

此外,使用async / await时更加清晰,请参见此处:

//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");
})();

您现在可以看到,敌人和食物装载是独立的异步操作,可以随意执行。您还可以在他的底部看到如何等待所有操作完成。