javascript - while 循环和承诺
问题描述
我试图更好地理解承诺方面的异步行为。我正在尝试使用永远的 while 循环来执行承诺。我已经阅读了几篇关于如何做到这一点的帖子,但我想了解为什么以下内容不起作用。
承诺.js
const promise = new Promise(function (resolve, reject) {
resolve('success');
reject('failed');
});
while (true) {
promise.then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
}
预期的:
$ node promises.js
success
success
success
success
...
这里...
意味着永远持续下去。
实际的:
$ node promises.js
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 00007FF7E2D7F04A v8::internal::GCIdleTimeHandler::GCIdleTimeHandler+5114
2: 00007FF7E2D5A0C6 node::MakeCallback+4518
3: 00007FF7E2D5AA30 node_module_register+2032
4: 00007FF7E2FE20EE v8::internal::FatalProcessOutOfMemory+846
5: 00007FF7E2FE201F v8::internal::FatalProcessOutOfMemory+639
6: 00007FF7E3502BC4 v8::internal::Heap::MaxHeapGrowingFactor+9556
7: 00007FF7E34F9C46 v8::internal::ScavengeJob::operator=+24310
8: 00007FF7E34F829C v8::internal::ScavengeJob::operator=+17740
9: 00007FF7E3500F87 v8::internal::Heap::MaxHeapGrowingFactor+2327
10: 00007FF7E3501006 v8::internal::Heap::MaxHeapGrowingFactor+2454
11: 00007FF7E30BCDB7 v8::internal::Factory::NewFillerObject+55
12: 00007FF7E3152CC6 v8::internal::WasmJs::Install+29414
13: 000001BD351DC5C1
在这里,该过程只是挂起然后出错。
我的理解是,因为 Promise 是异步的,所以使用标准的 while 循环是行不通的。我的猜测是,promise 被调用(如 in 调用promise.then(...).catch(...)
)更快,然后它们被解决?
是什么导致进程挂起然后用完堆内存?
解决方案
考虑这段代码:
const promise = new Promise(function (resolve, reject) {
resolve('success');
reject('failed');
});
var x = 0
while (x < 50) {
promise.then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
x++;
}
它就像你的一样,但它只运行 while 循环 50 次。如果你在 chrome 中运行它并设置断点,你会发现首先promise
变量被实例化为新的 Promise,然后 while 循环开始,promise.then..
运行的行,然后......
然后你期望接下来发生的可能是里面的函数.then
会运行,但是不,由于 Promise 的异步性质和 的同步性质while
,它会在没有运行内部函数的情况下x++
返回然后返回promise.then...
内部函数计划运行,但如果同步 javascript 从未停止运行,则它永远不会有机会运行。Javascript 是单线程的,因此您的循环版本会一直运行下去并进行更多.then
调用,填满堆栈和内存并中断。
在我的代码中,里面的函数在.then(
x = 50 之后运行,因为那是 while 循环停止同步运行的时候。
编辑
还要考虑这段代码:
var x = true;
function changeX(count) {
return new Promise(resolve => {
console.log('inside changeX');
setTimeout(function() {
if (count > 10) x = false;
resolve();
},100);
})
}
async function run() {
var count = 0;
while(x) {
await changeX(count);
count++;
}
console.log('x is false now');
}
run();
因为这使用 async await 语法,所以 while 循环的行为与您的 Promise 不同。如果您通过 webpack/babel 运行它以将其转换为 es5 Promise,您可能会发现它做了一些非常有趣的事情。
推荐阅读
- reactjs - 我在尝试实施 JWT 身份验证时收到此错误,错误:超过最大更新深度
- r - 如何在一个循环中选择最大元素在 r 中编写一个双循环?
- apache-spark-sql - 获取格式化为 yyyyMMdd 的字符串的 M/d/yyyy 或 MM/dd/yyyy 字符串
- r - R 子集/保留至少包含两个特定文本字符串的所有行
- python - 在 Jupyter Lab for New Environment 中导入 Pandas 时出现错误消息
- python - 代码在编写时有效,但在定义时无效
- javascript - 更改 Extjs GridPanel 顶栏分页工具的刷新按钮处理程序
- git - 将 git 子模块中的更改推送到主模块而不是子模块
- hadoop - 为什么我的 Yarn 显示的内存 (12 GB) 比主机 (32 GB) 少
- javascript - 在Javascript中实现加载器超时