提问人:Kondaveti Charan 提问时间:5/17/2023 最后编辑:Kondaveti Charan 更新时间:5/18/2023 访问量:101
将 promise 包装到 setTimer() 中而不是有什么意义?
what's the point of wrapping promise into setTimer() and not?
问:
promise 没有 setTimeout()
console.log('Prmoise start');
const lotteryPromise = new Promise(function (resolve, reject) {
if(Math.random() >= 0.5) {
resolve('You won the lottery');
} else {
reject(new Error('You lost your money'));
}
});
lotteryPromise.then(res => console.log(res)).catch(err => console.error(err));
console.log('Promise end');
promise 和 setTimeout()
console.log('Prmoise start');
const lotteryPromise = new Promise(function (resolve, reject) {
setTimeout( () => {
if(Math.random() >= 0.5) {
resolve('You won the lottery');
} else {
reject(new Error('You lost your money'));
}
},2000);
});
lotteryPromise.then(res => console.log(res)).catch(err => console.error(err));
console.log('Promise end');
我不明白 promise 中 setTimeout() 包装的用法?即使没有 setTimeout() wapping,promise 也会以异步方式执行,即它被添加到 eventQueue 中?是 SetTimeout 只是延迟了代码执行,还是我遗漏了什么?顺便说一句,我知道调用堆栈、微任务和回调队列是如何工作的......
答:
Promise.resolve 调度微任务,setTimeout 调度宏任务。微任务在运行下一个宏任务之前执行。
评论
Promise.resolve
通过向代码添加计时器,可以进一步确认 promise 中的代码是异步运行的。这只是为了模拟异步操作(如获取数据)的真实示例的行为。 它会等待 2 秒钟,然后执行您的操作并在之后解决。
你正在向后解决这个问题。你应该问:在没有setTimeout
的情况下使用promise有什么意义?
promise 的目的是以标准方式管理异步代码。
构造函数的目的是为异步代码创建一个 promise,该代码本身不使用 promise。new Promise
在第一个代码块中,传递给的函数没有任何异步内容。这是一个毫无意义的承诺。Promise()
在你的第二个代码块中,它是异步的,但你无法知道它何时完成(除了修改你传递给它的回调)。与它一起使用允许您在完成后使用 promise 对象执行某些操作。setTimeout
new Promise
setTimeout
也就是说,对于这个例子,根本没有明显的理由使用或承诺。它完全是为了演示 promise 的工作原理,而不是一个实际的例子,说明何时应该使用 promise 或超时。setTimeout
评论
承诺的一个略微错过的概念是,有异步。但实际上只有一个合约,然后它被放入一个队列中,该队列将在下一个事件循环之前进行处理。对于编写异步代码非常有用,比回调好得多。
下面是一个包含 2 个 promise 的简单示例,1 个 promise 不做任何异步操作,另一个执行简单的异步睡眠。异步休眠非常重要,因为这允许浏览器处理下一个事件循环。如果您取消此睡眠并重新运行,请观察浏览器将如何挂起。
请注意:准备好使用 Chrome 的任务管理器来杀死 浏览器 TAB 键,当您注释掉 .
await sleep(1)
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
async function nothingProm() {
// a promise that does no async stuff
}
//this infinate loop will not hang the browser
async function test() {
while (true) {
await nothingProm();
await sleep(1); //remove this for HANG!!!
}
}
test();
现在,在上面,为什么删除该睡眠会导致浏览器挂起,这似乎很奇怪。
浏览器使用一种称为事件循环的东西,它负责获取鼠标点击、计时器等内容,并将它们发送给侦听器。这与协作式多任务操作系统的工作方式非常相似,比如 Window 3.11。
因此,在浏览器 TAB 中,将有一个事件循环运行,执行类似 ->
while (running) {
var message = getNextMessage();
dispatchMessage(message);
}
上面的内容将有效地等待某些事件、计时器、鼠标移动等。因此,它不会浪费 CPU 资源,即使认为它处于这个紧密的循环中。getNextMessage
那么,这与你可能会问的承诺有什么关系呢?嗯,这个位是进来的地方,不像一个计时器,浏览器可以从中调度,基本上卡在一个队列中,在处理下一个之前被排空。microtask
macrotask
macrotask
while (running) {
var message = getNextMessage(); // (1)
dispatchMessage(message); // (2)
processMicroTaskQueue(); // (3)
}
因此,如果您有只执行阶段 (3) 的承诺,浏览器会不断卡在 (3),因此没有任何机会处理任何 , IOW:浏览器挂起!!macrotasks
希望这是有道理的,而且我使用了正确的术语等。
与 3.11 非常相似,一个写得不好的应用程序,从来没有给操作系统处理其事件循环的机会,实际上会挂起整个操作系统。 奇怪的是,这些事情怎么又来了。:)
评论
Promise.end
Even without the timer wrap the promise is asynchronously executing right ?
不。。它们只是在下一个宏任务之前排队运行。事实上,如果浏览器没有机会执行另一个宏任务,它甚至会像同步代码一样挂起浏览器。