Javascript 如何在递归创建承诺时避免内存泄漏?
我有一个ionic应用程序,它需要下载数据(带分页)并递归地将其插入数据库(如管道)。我用(Angular的)$q服务创造承诺。问题是,当我调用这个递归函数时,数据被成功下载和插入,但是内存使用率总是在增加,当承诺链完全解决时,分配的内存仍然在使用 这是我的递归函数:Javascript 如何在递归创建承诺时避免内存泄漏?,javascript,angularjs,recursion,ionic-framework,promise,Javascript,Angularjs,Recursion,Ionic Framework,Promise,我有一个ionic应用程序,它需要下载数据(带分页)并递归地将其插入数据库(如管道)。我用(Angular的)$q服务创造承诺。问题是,当我调用这个递归函数时,数据被成功下载和插入,但是内存使用率总是在增加,当承诺链完全解决时,分配的内存仍然在使用 这是我的递归函数: // offset: last downloaded row count // limit: row count to download at each page // numRows: row count to downl
// offset: last downloaded row count
// limit: row count to download at each page
// numRows: row count to download at all
function dowloadAndInsert(offset, limit, numRows) {
var deferred = $q.defer();
// Recursion step: We do not reached at the end of data
if((offset + limit) <= numRows) {
// Download the data
downloadData(offset, limit)
.then(function(response) {
// Insert the data
insertData(response)
.then(function(insertTime) {
// Recursion step
dowloadAndInsert(offset + limit, limit, numRows)
.then(function() {
deferred.resolve();
})
.catch(function(reason) {
deferred.reject(reason);
});
})
.catch(function(reason) {
deferred.reject(reason);
});
})
.catch(function(reason) {
deferred.reject(reason);
});
}
// Base case: We reached at the end of data
else {
var remainingRows = numRows % limit; // Means the last limit actually
// If exists, insert remaining rows
if(remainingRows !== 0) {
// Download the last piece of data
downloadData(offset, remainingRows)
.then(function(response) {
// Insert the last piece of data
insertData(response)
.then(function(insertTime) {
// Base case, successfully downloaded and inserted everything
deferred.resolve();
})
.catch(function(reason) {
deferred.reject(reason);
});
})
.catch(function(reason) {
deferred.reject(reason);
});
}
else {
// Base case, successfully downloaded and inserted everything
deferred.resolve();
}
}
return deferred.promise;
}
//偏移量:上次下载的行数
//限制:每页下载的行数
//numRows:要下载的行数
函数DOWLOANDINSERT(偏移、限制、numRows){
var deferred=$q.deferred();
//递归步骤:我们没有到达数据的末尾
如果((offset+limit)您的代码工作得太辛苦了,那么承诺链,因此当您跳一段延迟的舞蹈时,您实际上可以通过承诺链来解决泄漏问题,这是更好的代码的副作用:
function dowloadAndInsert(offset, limit, numRows) {
const start = offset,
numFetch = ((offset + limit) <= numRows ? limit : numRows % limit;
if(numFetch === 0) {
return Promise.resolve(); // we're done;
}
return downloadData(start, end).
then(insertData).
then(downloadAndInsert.bind(null, offset + numFetch, limit, numRows);
}
函数dowloadAndInsert(偏移、限制、numRows){
常数开始=偏移量,
numFetch=((offset+limit)你的代码工作得太辛苦了,承诺链,所以当你做一个小小的延迟舞蹈时,你真的可以把承诺链起来,这应该会解决泄漏问题,作为更好代码的副作用:
function dowloadAndInsert(offset, limit, numRows) {
const start = offset,
numFetch = ((offset + limit) <= numRows ? limit : numRows % limit;
if(numFetch === 0) {
return Promise.resolve(); // we're done;
}
return downloadData(start, end).
then(insertData).
then(downloadAndInsert.bind(null, offset + numFetch, limit, numRows);
}
函数dowloadAndInsert(偏移、限制、numRows){
常数开始=偏移量,
numFetch=((偏移量+限制)提问前请先搜索的可能副本。副本的措辞与您的标题几乎完全相同,当我搜索您的标题时,它的副本作为第二次点击(当然是在这个问题之后).Holy deferred anti pattern:您不应嵌套然后
s这听起来更可能是内存使用问题,而不是内存泄漏问题。只有在多次运行此操作并且每次运行时进程使用的总内存都会继续增加时,您才应怀疑有泄漏。承诺会自行解决问题I don’我不喜欢Javascript中的任何其他对象。你的工作是确保没有对不再需要的数据的持久引用。如果你这样做,就不会有泄漏。在提问之前,请先搜索的可能重复项。重复项的措辞与你的标题几乎完全相同,当我搜索你的标题时,我t的第二次点击是重复的(当然是在这个问题之后).Holy deferred anti pattern:您不应嵌套然后
s这听起来更可能是内存使用问题,而不是内存泄漏问题。只有在多次运行此操作并且每次运行时进程使用的总内存都会继续增加时,您才应怀疑有泄漏。承诺会自行解决问题我不喜欢Javascript中的任何其他对象。你的工作是确保不存在对不再需要的数据的持久引用。如果你这样做,就不会有泄漏。这建议了一种更干净的方法来编写promise代码,但我不确定它是否真的解决了问题的实质,即操作需要多少内存nsuming(参见问题的最后一段),OP似乎认为这是一个泄漏(但尚未显示这是内存使用问题还是实际泄漏).@jfriend00如果不使用4级嵌套闭包,内存使用率应该会低得多,这在执行递归时会非常昂贵。这里-没有保留闭包-您需要的唯一跟踪是下一个承诺,并且只有在这个承诺解决时才开始,因此不必保留内存。现在要完全公平,泄漏是很棘手的术语——如果我们只考虑泄漏,最终没有得到清理——你是正确的-但是如果我们考虑泄露,当操作不需要时,消耗越来越多的内存,这个代码不会泄露在智能承诺库中,在跟踪结束PROM后,它们可以跳过中间承诺。ise。我不确定$q是否会这样做,因为我已经一年多没有看过它了——但我希望如此。如果您认为您的代码建议有助于解决OP存在的内存泄漏/使用问题,那么请将该信息添加到您的答案文本中,并解释您认为问题可能会如何解决。我没有从您的答案中获得该信息。这不是解决了我的问题。我的问题不是因为递归承诺链,而是因为大数据的使用。我通过将下载和插入操作放入一个单独的函数并调用它,而不是将大数据保留在递归函数中,从而减少了内存的使用。这建议了一种更干净的方法来编写承诺代码,但我不确定它实际上解决了问题的真正点,即操作消耗了多少内存(参见问题的最后一段),OP似乎认为这是一个泄漏(但这还没有显示这是内存使用问题还是实际泄漏).@jfriend00如果不使用4级嵌套闭包,内存使用率应该会低得多,这在执行递归时会非常昂贵。这里-没有保留闭包-您需要的唯一跟踪是下一个承诺,并且只有在这个承诺解决时才开始,因此不必保留内存。现在要完全公平,泄漏是很棘手的术语——如果我们只考虑泄漏,最终没有得到清理——你是正确的-但是如果我们考虑泄露,当操作不需要时,消耗越来越多的内存,这个代码不会泄露在智能承诺库中,在跟踪结束PROM后,它们可以跳过中间承诺。ise。我不确定$q是否会这样做,因为我已经一年多没有看过它了——但我希望如此。如果您认为您的代码建议有助于解决OP存在的内存泄漏/使用问题,那么请将该信息添加到您的答案文本中,并解释您认为问题可能如何