使用非常简单的Angular视频指令进行内存泄漏

时间:2015-04-21 09:08:27

标签: angularjs memory-leaks html5-video

在我使用Angular和其他东西的大型应用程序中,我目前在不同应用程序页面的导航中遇到严重的内存泄漏。

该页面的视频和图像非常丰富,似乎不会被垃圾收集。主要泄漏来自视频,这是btw页面上加载的最大文件。我使用常见的泄漏源进行了两天的搜索,例如ngAnimate,dom元素上的jquery事件以及unancelled $ timeout但我无法找到问题。

我最终在一个非常简单的应用程序中隔离了视频指令,我可以重现chrome上的泄漏。您可以在下面看到chrome dev工具中的图表以及运行应用程序的完整代码:

Memory timeline navigation from page to page

的index.html

<!DOCTYPE html>
<html lang="en">
<head runat="server">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
</head>
<body>
    <div ng-app="app">
        <ul class="nav">
            <li><a ng-href="#/">page1</a></li>
            <li><a ng-href="#/page2">page2</a></li>
        </ul>
        <div>
            <div ng-view=""></div>
        </div>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-route.js"></script>
    <script src="app.js"></script>
</body>
</html>  

page1.tpl.html

<div>
    <h1>{{title}}</h1>
    <div class="videoBlock" ng-if="loaded">
        <html5video source="{{ videoToRender }}" preload="none" autoplay="autoplay" muted="muted" loop="loop">
        </html5video>
    </div>
</div>

page2.tpl.html

<div>
    <h1>{{title}}</h1>
    <p>Empty page</p>
</div>

Html5Video指令模板:html5video.tpl.html

<video class="videoBack">
    <source type="video/mp4" ng-src="{{trustSrc(sources.mp4)}}">
    <source type="video/webm" ng-src="{{trustSrc(sources.webm)}}">
    <source type="video/ogg" ng-src="{{trustSrc(sources.ogv)}}">
</video>

所有代码都包含在app.js中:html5video指令使用pageConfigService从配置文件构建视频网址,并使用它构建html5视频标记。

app.js

(function () {
    'use strict';

    var app =angular.module('app', [
        'ngRoute',
        'directives',
        'services'
    ]);


    app.config(['$routeProvider',
        function ($routeProvider) {
            $routeProvider
                .when('/', {
                    templateUrl: 'page1.tpl.html',
                    controller: 'Page1Ctrl'
                })
                .when('/page2', {
                    templateUrl: 'page2.tpl.html',
                    controller: 'Page2Ctrl'
                });
        }
    ]);


    app.controller('Page1Ctrl', ['$scope', 'pageConfigService', function Page1Ctrl($scope, pageConfigService) {
        $scope.title = "Page 1";
        $scope.loaded = false;
        pageConfigService.getConsumerIndexConfigAsync().success(function (config) {
            $scope.videoToRender = config.videoPath;
            $scope.loaded = true;
        })
    }]);



    app.controller('Page2Ctrl', ['$scope', function Page2Ctrl($scope) {
        $scope.title = "Page 2";
    }]);



    // services
    angular
        .module('services', [])
        .factory('pageConfigService', ['$http', function ($http) {
            return {
                getConsumerIndexConfigAsync: getConsumerIndexConfigAsync
            }

            function getConsumerIndexConfigAsync() {
                return $http.get('consumerIndex2.json');
            }
        }]);


    // directives
    angular
        .module('directives', [])
        .directive('html5video',
            function () {

                return {
                    restrict: 'E',
                    priority: 1001,
                    replace: true,
                    templateUrl: 'html5video.tpl.html',
                    scope: {
                        source: "@",
                        reloaded: "@"
                    },
                    link: link
                }

                function link(scope, element, attrs) {

                    scope.sources = {
                        'mp4': attrs.source + '.mp4',
                        'webm': attrs.source + '.webm',
                        'ogv': attrs.source + '.ogv'
                    }

                    scope.trustSrc = function (src) {
                        return $sce.trustAsResourceUrl(src);
                    }

                }
            }
        );

}());

consumerIndex2.json

{
  "videoPath": "http://vjs.zencdn.net/v/oceans"  
}

你能帮我StackOverflow吗? :)

1 个答案:

答案 0 :(得分:0)

的Bonjour,

Je serais curieux de voir tonimplémentationfinale。 Car j'ai unpeupectéetavec uneversionépuréedetype

<video id="myVideo" class="videoBack"><source type="video/mp4" src="http://vjs.zencdn.net/v/oceans.mp4"></video>

Je constatais que les noeuds Video et Source ne sontpasrelâchés。 Par contre je n'ai plusdeproplèmesèsqu'iln'y plus de balise source。 Etcemalgrél'etilrationd'un empty dans le'destroy'