为什么回调地狱起作用而 async/await 不起作用? (在我正在测试的这种特殊情况下)
Why does the callback hell works and the async/await doesnt? (in this particular case that i am testing)
我有这两个代码(一个我使用回调地狱,另一个 async/await):
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const callBackHell = () => {
return Promise.resolve().then((v) => {
sleep(1);
console.log("ameno");
return Promise.resolve().then((v) => {
sleep(1);
console.log("dorime");
return Promise.resolve().then((v) => {
sleep(1);
return console.log("latireno");
});
});
});
};
console.log(1);
callBackHell();
console.log(2);
console.log(3);
回调地狱如我想象的那样工作(字符串日志最后出现)。
然后我尝试转换相同的代码,但使用 async/await,像这样:
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
现在第一个 await 阻塞了主线程,而另外两个则一直显示在 last。我做错了什么?
使用@Muhammad Saquib Shaikh 解决方案编辑:
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
(async function () {
console.log(1);
await codeBlockerAwait();
console.log(2);
console.log(3);
})();
它与第一个输出不同。
Now the first await blocks the main thread while the other two keeps showing lastly. What am i doing wrong?
ameno
被预先记录的原因是您在 任何 await
之前有该日志语句 。要评估行 await consoleMusical("ameno");
,它必须执行 consoleMusical('ameno')
,获取其 return 值,然后才能 await
.
另一个 console.logs 发生在 await 之后,因此它们将作为微任务排队到 运行 在当前正在执行的代码的其余部分之后。
相比之下,callBackHell 的所有 console.logs 都在第一个 promise 中。所以它们都将作为微任务排队。
如果您使用异步睡眠而不是同步睡眠,这个问题就会消失。作为奖励,您不会锁定浏览器:
function sleep(seconds) {
return new Promise(resolve => {
setTimeout(resolve, seconds * 1000);
});
}
const consoleMusical = async (letra) => {
await sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
如果您绝对必须进行同步睡眠,同时仍希望保持相同的操作顺序,则需要添加一个额外的等待。
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await undefined; // <--------- added
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
.then
代码保证异步执行。因此,callBackHell
returns 立即。
codeBlockerAwait
,另一方面,仅当执行 await
时产生 returns。这发生在 consoleMusical("ameno")
完成执行之后。
如果你有一个更现实的例子,事情就会更加相似。例如,如果我们用异步函数替换阻塞 sleep
函数,您将获得预期的行为。
function sleep(seconds) {
return new Promise(
(resolve, reject) => {
setTimeout(resolve, seconds * 1000);
}
);
}
const consoleMusical = async (letra) => {
await sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
我有这两个代码(一个我使用回调地狱,另一个 async/await):
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const callBackHell = () => {
return Promise.resolve().then((v) => {
sleep(1);
console.log("ameno");
return Promise.resolve().then((v) => {
sleep(1);
console.log("dorime");
return Promise.resolve().then((v) => {
sleep(1);
return console.log("latireno");
});
});
});
};
console.log(1);
callBackHell();
console.log(2);
console.log(3);
回调地狱如我想象的那样工作(字符串日志最后出现)。
然后我尝试转换相同的代码,但使用 async/await,像这样:
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
现在第一个 await 阻塞了主线程,而另外两个则一直显示在 last。我做错了什么?
使用@Muhammad Saquib Shaikh 解决方案编辑:
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
(async function () {
console.log(1);
await codeBlockerAwait();
console.log(2);
console.log(3);
})();
它与第一个输出不同。
Now the first await blocks the main thread while the other two keeps showing lastly. What am i doing wrong?
ameno
被预先记录的原因是您在 任何 await
之前有该日志语句 。要评估行 await consoleMusical("ameno");
,它必须执行 consoleMusical('ameno')
,获取其 return 值,然后才能 await
.
另一个 console.logs 发生在 await 之后,因此它们将作为微任务排队到 运行 在当前正在执行的代码的其余部分之后。
相比之下,callBackHell 的所有 console.logs 都在第一个 promise 中。所以它们都将作为微任务排队。
如果您使用异步睡眠而不是同步睡眠,这个问题就会消失。作为奖励,您不会锁定浏览器:
function sleep(seconds) {
return new Promise(resolve => {
setTimeout(resolve, seconds * 1000);
});
}
const consoleMusical = async (letra) => {
await sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
如果您绝对必须进行同步睡眠,同时仍希望保持相同的操作顺序,则需要添加一个额外的等待。
function sleep(seconds) {
const date = Date.now();
milliseconds = seconds * 1000;
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
const consoleMusical = async (letra) => {
sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await undefined; // <--------- added
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);
.then
代码保证异步执行。因此,callBackHell
returns 立即。
codeBlockerAwait
,另一方面,仅当执行 await
时产生 returns。这发生在 consoleMusical("ameno")
完成执行之后。
如果你有一个更现实的例子,事情就会更加相似。例如,如果我们用异步函数替换阻塞 sleep
函数,您将获得预期的行为。
function sleep(seconds) {
return new Promise(
(resolve, reject) => {
setTimeout(resolve, seconds * 1000);
}
);
}
const consoleMusical = async (letra) => {
await sleep(1);
console.log(letra);
};
async function codeBlockerAwait() {
await consoleMusical("ameno");
await consoleMusical("dorime");
await consoleMusical("latiereno");
}
console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);