这是《 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.
答案 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");
})();
您现在可以看到,敌人和食物装载是独立的异步操作,可以随意执行。您还可以在他的底部看到如何等待所有操作完成。