Javascript 在第n次设置超时中解决的承诺是否会导致内存泄漏?
我可以在Chrome任务管理器中看到,运行以下代码的选项卡占用了越来越多的内存,在承诺得到解决之前,它不会被释放 更新 这里的主要思想是使用一个“低级”方法来处理来自服务器的“繁忙”响应。其他方法只是将带有请求数据的url路径传递给它,并等待有价值的响应 一些反模式被删除Javascript 在第n次设置超时中解决的承诺是否会导致内存泄漏?,javascript,memory-leaks,es6-promise,Javascript,Memory Leaks,Es6 Promise,我可以在Chrome任务管理器中看到,运行以下代码的选项卡占用了越来越多的内存,在承诺得到解决之前,它不会被释放 更新 这里的主要思想是使用一个“低级”方法来处理来自服务器的“繁忙”响应。其他方法只是将带有请求数据的url路径传递给它,并等待有价值的响应 一些反模式被删除 var counter = 1 // emulates post requests sent with ... axios async function post (path, data) { let respons
var counter = 1
// emulates post requests sent with ... axios
async function post (path, data) {
let response = (counter++ < 1000) ? { busy: true } : { balance: 3000 }
return Promise.resolve(response)
}
async function _call (path, data, resolve) {
let response = await post()
if (response.busy) {
setTimeout(() => {
_call(path, data, resolve)
}, 10)
throw new Error('busy')
}
resolve(response.balance)
}
async function makePayment (amount) {
return new Promise((resolve, reject) => {
_call('/payment/create', {amount}, resolve)
})
}
async function getBalance () {
return new Promise((resolve, reject) => {
_call('/balance', null, resolve)
})
}
makePayment(500)
.then(() => {
getBalance()
.then(balance => console.log('balance: ', balance))
.catch(e => console.error('some err: ', e))
})
var计数器=1
//模拟使用…发送的post请求。。。axios
异步函数post(路径、数据){
let response=(计数器+++<1000)?{busy:true}:{balance:3000}
返回承诺。解决(响应)
}
异步函数调用(路径、数据、解析){
let response=wait post()
如果(响应。忙){
设置超时(()=>{
_调用(路径、数据、解析)
}, 10)
抛出新错误('busy')
}
解决(响应、平衡)
}
异步函数makePayment(金额){
返回新承诺((解决、拒绝)=>{
_调用('/payment/create',{amount},resolve)
})
}
异步函数getBalance(){
返回新承诺((解决、拒绝)=>{
_调用('/balance',null,resolve)
})
}
付款(500)
.然后(()=>{
getBalance()
.then(balance=>console.log('balance:',balance))
.catch(e=>console.error('someerr:',e))
})
第一次在此处调用\u call()
:
async function getBalance () {
return new Promise((resolve, reject) => {
_call('/balance', null, resolve)
})
}
它不会调用resolve回调,它将返回一个被拒绝的承诺,因此您在getBalance()
中的new promise()
最初将什么也不做。请记住,由于\u call
标记为async
,当您抛出时,它会被捕获并变成拒绝的承诺
当计时器启动时,它将调用resolve()
,这将解析getBalance()
承诺,但它没有值,因此您无法获得余额。当您最终调用resolve(response.balance)
时,您已经调用了resolve()
函数,因此它所属的承诺被锁定,并且不会更改其值
正如其他人所说,这段代码有各种各样的错误(很多反模式)。当我在node.js或答案中的代码段中运行它时,这里有一个简化版本:
功能延迟(t,val){
返回新承诺(解决=>{
setTimeout(resolve.bind(null,val),t);
});
}
var计数器=1;
职能职位(){
log(`counter=${counter}`);
//出于演示目的,此处将计数器值修改为100
返回(计数器+++<100){busy:true}:{balance:3000};
}
函数getBalance(){
异步函数_call(){
let response=post();
如果(响应。忙){
//延迟,然后连接下一个呼叫
等待延迟(10);
返回调用();
}否则{
返回响应。平衡;
}
}
//开始整个过程
返回调用();
}
getBalance()
.then(balance=>console.log('balance:',balance))
.catch(e=>console.error('some error:',e))
,避免错误,不要传递resolve
,在最小级别上承诺(setTimeout
),不要抛出从未捕获到的错误!不确定内存,但该代码几乎包含了所有promise反模式:p此代码应积累“未处理的promise rejection”错误,但不应泄漏其自身的任何内存。使用10ms计时器反复调用自己可能不会给垃圾收集器足够的时间来完成其正常工作。这可能是在整个过程完成之前,内存不断增加的部分原因。仅供参考,这里有一个删除promise反模式的代码清理版本:这都是真的(尽管async
/await
代码可以进一步简化为使用循环而不是递归),但这并不能解释为什么OP会发生内存泄漏?