在多次文件请求后,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 上停止的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS 在多次请求后无限期挂起

服务器在一分钟内多次发布请求后没有响应

.NET HttpClient 在多次请求后挂起(除非 Fiddler 处于活动状态)

后端处理高并发状态的多次重复请求

jquery ajax请求时如果页面卡主 多次发出相同请求 如何处理

在使用python执行期间多次将请求的响应写入json文件