在多次文件请求后,Cordova-Angularjs 应用程序在 iPad 上停止
Posted
技术标签:
【中文标题】在多次文件请求后,Cordova-Angularjs 应用程序在 iPad 上停止【英文标题】:Cordova-Angularjs App stops on iPad after many file requests 【发布时间】:2014-12-15 11:27:09 【问题描述】:我正在尝试使用 Cordova 和 AngularJs 编写一个 iPad 应用程序,它会在启动时自行更新。因此,当应用程序过期时,我会复制许多文件(js、css、图像...)。
iPad-App 冻结大约 400 个文件后,不再处理延迟事件。我已经剥离了我的应用程序并来到了这个测试应用程序,它基本上只是连续初始化文件系统 10000 次:
<!-- language: lang-js -->
angular.module('tablet', []).controller('StartCtrl', ['$scope', '$http', '$q',
function($scope, $http, $q)
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady()
console.log('deviceready');
testFileSystem($q);
]);
function testFileSystem($q)
var defer = $q.defer();
var chain = defer.promise;
defer.resolve();
// chaining 10000 init filesystem requests
for (var i = 0; i < 10000; i++)
chain = chain.then(startInitFileSystem($q, i));
function startInitFileSystem($q, i)
return function()
return initFileSystem($q, i);
function initFileSystem($q, i)
console.log('Init FileSystem: ' + i);
var defer = $q.defer();
window.requestFileSystem(PERSISTENT, 1024 * 1024 * 1024, function(fs)
fileSystem = fs;
defer.resolve();
, function()
console.log("Init FileSystem failed");
defer.reject();
);
return defer.promise;
在 997 次请求后,应用停止后不再触发延迟事件。在调试 angularjs defer 对象时,我可以将问题缩小到方法:
<!-- language: lang-js -->
self.defer = function(fn, delay)
var timeoutId;
outstandingRequestCount++;
try
timeoutId = setTimeout(function()
delete pendingDeferIds[timeoutId];
completeOutstandingRequest(fn);
, delay || 0);
catch (e)
console.log(e.message);
pendingDeferIds[timeoutId] = true;
return timeoutId;
;
“setTimeout”被调用,但发生错误时不触发。
这可能是某种内存泄漏吗?令人惊讶的是,如果您不使用角度延迟,它会起作用。有没有办法在解决延迟后清理它?
我正在使用 cordova 插件:设备、记录器和文件。
【问题讨论】:
您的问题解决了吗?我在没有任何线索的情况下面临同样的问题...... 【参考方案1】:我也有同样的问题。问题是您的内存正在运行,完全导致 ios 设备上的 setTimeout 发生泄漏。
您可以通过使用工具并运行分配工具来验证这一点。在真实设备上运行您的示例并连接到该进程。连接后运行您的示例。您应该看到一个不断增长的分配图。当您在不使用任何 setTimeout 调用的情况下重新实现示例时,垃圾收集器正在清除所有内容。请注意垃圾收集有点懒惰,只有在分配了一定数量的内存后才开始。所以你需要重新运行你的代码。
我在创建测试cordova项目时添加到app对象的示例代码:
run: function ()
function error(err)
alert(err);
window.requestFileSystem(window.PERSISTENT, 0, function (fs)
function tick(i)
return function ()
if (i > 1000) return;
fs.root.getDirectory(String(i), create: true , function ()
setTimeout(next(i + 1), 0); // Removing setTimeout solves the memory leak
, error);
;
tick(0)();
, error);
请注意,即使函数完成处理,内存分配也会保持不变,如果没有 setTimeout,内存将在处理完成后被垃圾收集。我目前不知道为什么会发生这种情况,但是如果它真的与 setTimeout 调用有关,则应用中的每个调用都可能导致泄漏。
【讨论】:
以上是关于在多次文件请求后,Cordova-Angularjs 应用程序在 iPad 上停止的主要内容,如果未能解决你的问题,请参考以下文章
.NET HttpClient 在多次请求后挂起(除非 Fiddler 处于活动状态)