Javascript 承诺+;jqueryajax链使内存增长。我用对了吗?
我有一个JS,它必须定期执行远程操作,然后对其做出反应。流程是:Javascript 承诺+;jqueryajax链使内存增长。我用对了吗?,javascript,jquery,ajax,memory-leaks,promise,Javascript,Jquery,Ajax,Memory Leaks,Promise,我有一个JS,它必须定期执行远程操作,然后对其做出反应。流程是: - Start the operation in main script -> `setInterval` calling a function every 5 seconds -> This function waits for a `Promise` that internally... -> ... calls `$.ajax`, validate the response,
- Start the operation in main script
-> `setInterval` calling a function every 5 seconds
-> This function waits for a `Promise` that internally...
-> ... calls `$.ajax`, validate the response, then resolve or reject.
我看到我的应用程序内存在增长,这个操作链可能是原因。我使用承诺的方式正确吗
主要的切入点很简单:
StateWatcher.startWatchSystem();
然后,所涉及的模块:
var StateWatcher = {
// is called by the main app to start the backround check every 5 sec
// the actual function that performs the update is "doSystemStateUpdate"
startWatchSystem: function() {
this.doSystemStateUpdate();
this.systemWatchTimeout = setInterval(() => {
this.doSystemStateUpdate();
}, 5000)
},
<...>
// this is "doSystemStateUpdate": the remote call is performed by another module "RemoteQuery.getSystemState()".
// that last function returns a Promise (see below), so I can check the result with "then" and "catch"
doSystemStateUpdate: function() {
RemoteQuery.getSystemState()
.then((data) => {
// ok, got the new State
this.currentSystemState = data.Message;
// ... inform other modules etc etc...
})
.catch((error) => {
Logger.write("error", "doSystemStateUpdate:");
Logger.write("error", error);
});
}
}
var StateWatcher={
//由主应用程序调用,每5秒启动一次回溯检查
//执行更新的实际函数是“doSystemStateUpdate”
startWatchSystem:函数(){
this.doSystemStateUpdate();
this.systemWatchTimeout=setInterval(()=>{
this.doSystemStateUpdate();
}, 5000)
},
//这是“doSystemStateUpdate”:远程调用由另一个模块“RemoteQuery.getSystemState()”执行。
//最后一个函数返回一个承诺(见下文),因此我可以用“then”和“catch”检查结果
doSystemStateUpdate:函数(){
RemoteQuery.getSystemState()
。然后((数据)=>{
//好的,有了新的状态
this.currentSystemState=data.Message;
//…通知其他模块等。。。
})
.catch((错误)=>{
write(“错误”,“doSystemStateUpdate:”);
Logger.write(“错误”,error);
});
}
}
以下是“RemoteQuery”模块:
var-RemoteQuery={
连接错误:错误,
//getSystemState在内部调用jQueryAjax,但随后将其封装在一个承诺中
//当Ajax完成时,在实际解决承诺之前,它必须使用函数“validateResponse”对Ajax结果进行快速检查
getSystemState:函数(){
返回新承诺((解决、拒绝)=>{
$.ajax({
数据类型:“json”,
网址:,
方法:“获取”,
cache:false,
成功:函数(数据){RemoteQuery.validateResponse(true,resolve,data)},
错误:函数(xhr,opts,error){RemoteQuery.validateResponse(false,reject,xhr)}
});
})
}
//这是最后一步:如果ajax操作不正常,此函数将设置一个“报警”标志。
//最后,它调用函数来解析承诺
validateResponse:函数(确定,然后是args){
if(this.connectionError==false&&ok==false){
this.connectionError=true;
//做其他事情(记录等)
}
else if(this.connectionError==true&&ok==true){
this.connectionError=false;
//做其他事情(记录等)
}
然后(args);//现在根据在ajax->success或ajax->error之后调用它的方式来解析或拒绝
},
}
因此,即使前一个请求尚未完成,您也希望每5秒请求一次吗?另外,ajax文档声明,.then()
promise是成功回调选项的另一种构造
,因此我想这是您的代码“遵循两个方向”的地方,而不是在done()/then()或success()中执行所有操作看不到任何可能导致内存泄漏的内容,但您可以通过编写返回$.ajax(…)。然后(…).catch(…)
并放弃新承诺()
包装来简化。此模式还允许您将validateResponse()
代码滚动到getSystemState()
中,并允许validateResponse()
响应作为单独的函数消失。这是一个更好的解决方案,尽管我怀疑它能修复内存泄漏。@Roamer-1888我知道我可以用then/catch(但为什么不能用done/fail?)替换jQuery的错误/成功。。。无论如何,我不确定为什么这将允许我删除validateResponse()
。如何在getSystemState()
中滚动它?它也被其他函数使用,所以我没有信心复制/粘贴它的主体。。。你能提供一个代码示例吗?如果在别处调用了validateResponse()
,请忽略我的建议。您仍然应该使用.then()
&.catch()
。在jQueryV3+中,它们具有所谓的“过滤能力”,成功:/error:`and.done()&
.fail()`not。使用.then()
和.catch()
时,抛出错误的返回值将沿着承诺链传播。
var RemoteQuery = {
connectionError: false,
// the getSystemState internally calls jQuery AJAX but then enclose it in a Promise
// When Ajax finishes, before actually resolve the promise it must do a quick check on the Ajax result, using function "validateResponse"
getSystemState: function () {
return new Promise((resolve, reject) => {
$.ajax({
dataType: "json",
url: <.... http...>,
method: "GET",
cache: false,
success: function(data) { RemoteQuery.validateResponse(true, resolve, data) },
error: function(xhr, opts, error) { RemoteQuery.validateResponse(false, reject, xhr) }
});
})
}
<...>
// this is the last step: this function sets an "alarm" flag if the ajax operation was not ok.
// at the end, it calls the function to resolve the promise
validateResponse: function(ok, then, args) {
if (this.connectionError == false && ok == false) {
this.connectionError = true;
// do other stuff (logging,...)
}
else if (this.connectionError == true && ok == true) {
this.connectionError = false;
// do other stuff (logging,...)
}
then(args); // now resolve or reject based on how it has been called after ajax->success or ajax->error
},
}