【问题标题】:Callback not being invoked未调用回调
【发布时间】:2018-05-01 14:59:20
【问题描述】:

我正在构建自定义 Power BI 可视化,因此我可以访问平台使用的 javascript 文件。我无权访问任何标记,只能在我要安装可视化的位置注入一个元素。

我正在尝试安装 Bing 地图,文档如下所示:

    <div id='myMap' style='width: 100vw; height: 100vh;'></div>

    <script type='text/javascript'>
            var map;
            function loadMapScenario() {
                map = new Microsoft.Maps.Map(document.getElementById('myMap'), {});
            }


    </script>

    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?key=YourBingMapsKey&callback=loadMapScenario' async defer></script>

脚本的 URL 有一个 callback 查询字符串参数,其中包含要调用的函数的名称。

鉴于我无权访问标记,我正在尝试在可视化的构造函数中动态地执行所有操作。我创建了一个函数,将其移至全局范围,然后添加查询字符串 var 以引用它,但它从未被调用。你能看到我可能遗漏的任何东西吗?

constructor(options: VisualConstructorOptions) {
        this.host = options.host;
        this.elem = options.element;
        const self = this;

        function moveMethodsIntoGlobalScope(functionName){
            var parts = functionName.toString().split('\n');
            eval.call(window, parts.splice(1, parts.length - 2).join(''));  
        }

        function methodsToPutInGlobalScope(){
            function loadMapScenario(){
                console.log("finally called loadMapScenario");
            }
        }

        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;

        console.log(loadMapScenario === undefined); // false, definitely in global scope
        script.src = 'https://www.bing.com/api/maps/mapcontrol?key=xxxxxxxxxx&callback=loadMapScenario';
        document.getElementsByTagName('head')[0].appendChild(script);

【问题讨论】:

    标签: javascript powerbi


    【解决方案1】:

    您已经定义了完成您想要的功能所需的功能。但是,在您给出的 sn-p 中,您实际上并没有调用 moveMethodsIntoGlobalScope(),这就是未定义 loadMapScenario 的原因。只需在注入脚本之前添加这一行。

    moveMethodsIntoGlobalScope(methodsToPutInGlobalScope);
    

    【讨论】:

      【解决方案2】:

      使用 foo===undefined 的行为会因运行时不同而有所不同。检查变量是否存在时,请改用 typeof foo。

      您正在使用 script.async 这将使脚本在所有其他脚本之后加载,但您可能希望在其他脚本之前加载它。

      另一个技巧是劫持window.onload ...

      【讨论】:

        【解决方案3】:

        要将方法放入浏览器的全局范围内,您可以使用更简单的方法,例如:

        window.loadMapScenario = () => {
          console.log("finally called loadMapScenario")
        }
        

        我认为您不需要 moveMethodsIntoGlobalScopemethodsToPutInGlobalScope - 在任何情况下,您都不会从这段代码中调用它们中的任何一个。

        【讨论】:

          【解决方案4】:

          我觉得这段代码就够了:

          window.loadMapScenario = function() {
            console.log("finally called loadMapScenario");
          }
          
          const script = document.createElement('script');
          script.type = 'text/javascript';
          script.async = true;
          script.src = `https://www.bing.com/api/maps/mapcontrol?key=${API_KEY}&callback=loadMapScenario`;
          document.getElementsByTagName('head')[0].appendChild(script);
          

          这是一个 JSFiddle,您可以使用 API_KEY 进行尝试:https://jsfiddle.net/9mfzrcfd/2/

          【讨论】:

            猜你喜欢
            • 2018-01-09
            • 2014-05-30
            • 2014-12-31
            • 2019-02-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多