【问题标题】:AngularJS Dynamically Loading Plain Old Javascript Through Source TagAngularJS 通过源标签动态加载普通的旧 Javascript
【发布时间】:2015-01-01 07:09:43
【问题描述】:

我正在尝试使用 AngularJS 承诺动态加载一些 javascript。

HTML 文件 (index.html)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-route.js"></script>
    <script type="text/javascript" src="main.js"></script>

    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body ng-app="main">

<ng-view></ng-view>

</body>
</html>

AngularJS 文件 (main.js)

angular.module('main', ['ngRoute'])
    .config(function($routeProvider) {
        $routeProvider
            .when('/',
            {
                controller: 'MainCtrl',
                templateUrl: 'partial.html',
                resolve: {
                    temp: MainCtrl.testFn
                }
            })
            .otherwise({
                redirectTo: '/'
            })
    })

MainCtrl = angular.module('main')
    .controller('MainCtrl', function () {

    });

angular.module('main')
    .factory('MyFactory', function($q) {
        data = {
            loadJS: function() {
                var deferred = $q.defer()
                var script = document.createElement('script');
                script.type = 'text/javascript'
                script.src = 'https://apis.google.com/js/client.js'
                script.onload = function() {
                    deferred.resolve('Google Client Library loaded')
                }
                document.body.appendChild(script)
                return deferred.promise
            }
        }
        return data
    })

MainCtrl.testFn = function($log, MyFactory) {
    return MyFactory.loadJS().then(function(result) {
        $log.debug(result)
        gapi.client.load()
    })
}

调用了 onload 方法(因为 promise 被解析并打印了调试行),但是由于在 gapi 上找不到客户端属性(未捕获的类型错误:无法读取未定义的属性“加载”)而引发错误。

我错过了什么?有没有人有更好的方法来动态加载带有 Angular 承诺的 JS(仅使用 Angular 和 JS)?

【问题讨论】:

  • 你为什么不使用像 requireJS 这样的适当加载器,或者只是在页面中包含带有链接的脚本标签?虽然这是可能的,但你最好有充分的理由
  • 我想避免加载和使用 javascript 之间的竞争条件。在我的真实应用程序中,我有一堆必须在路由发生之前解决的链式 Angular 承诺。我还没有研究过 requireJS b/c 我希望能找到一个好的 Angular 唯一解决方案。

标签: javascript html angularjs google-api angular-promise


【解决方案1】:

我猜,脚本加载成功,但 gapi.client 不能立即使用。为此,您需要向 google api url 提供处理程序(一些全局函数)。

angular.module('app', [])

.controller('mainCtrl', function(googleClientLoader) {
  googleClientLoader.load().then(
    function() {
      console.debug(gapi.client);
    }
  )
})

.factory('googleClientLoader', function($q) {
  return {
    load: function() {
      var deferred = $q.defer()
      var script = document.createElement('script');
      script.type = 'text/javascript'
      script.src = 'https://apis.google.com/js/client.js?onload=handleClientLoad';
      window.handleClientLoad = function() {
        deferred.resolve('Google Client Library loaded');
      }
      document.body.appendChild(script)
      return deferred.promise;
    }
  }
})

【讨论】:

    【解决方案2】:

    只需加载内容并使用 eval(data) 来评估 Javascript。 标签在页面加载后生成,不会被处理。

    【讨论】:

    • 鼓励人们使用 'eval' 从来都不是一件好事。这是一个很大的漏洞。
    猜你喜欢
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多