递归创建promises时如何避免内存泄漏?

时间:2016-08-18 20:05:40

标签: javascript angularjs recursion ionic-framework promise

我有一个离子应用程序需要下载数据(带分页)并以递归方式将其插入数据库(如管道)。我正在使用(Angular' s)$ q服务创建承诺。问题在于,当我调用这个递归函数时,数据正在被下载并成功插入,但是内存使用总是在增加,并且当promise链完全解析时,分配的内存仍然在使用中。

这是我的递归函数:

// 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;
}

注意:来自downloadData函数的响应对象是一个大数据,它有时包含100.000行,包含18列。总内存使用量变为1GB。我在iPad Air 2上运行我的测试。

我在递归函数中使用大数据,所以我的问题与其他递归内存泄漏问题有点不同。

感谢。

1 个答案:

答案 0 :(得分:3)

你的代码工作方式太难了,承诺链,所以当你做一点延期舞蹈时 - 你真的可以链接应该解决泄漏的承诺作为更好的代码的副作用:

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);
}

这就是整个代码,它说:

  • 检查我需要提取和插入的行数。
  • 如果我不需要再获取行 - 只需返回一个空的承诺。
  • 否则我们需要多次获取 - 然后获取剩余的行。