【问题标题】:Debugging JavaScript with asynchronous functions in third-party libraries?在第三方库中使用异步函数调试 JavaScript?
【发布时间】:2017-03-01 21:11:46
【问题描述】:

我正在与https://github.com/sameer-shelavale/blitz-gmap-editor 合作;文件test5.html 允许你放置一个标记,当你点击它时,你会得到一个表单来编辑它的属性:

我首先添加了一些额外的按钮,这些按钮添加了带有预填充数据的标记。然后,我单击它们以显示表单,我在表单中没有编辑任何内容,然后按取消。大约半秒到一秒后,我进入浏览器控制台:

TypeError: a.url.substr is not a function  util.js:202:114

我非常想摆脱这个错误(注意它不会出现在原来的test5.html 中)。

问题是——首先我不知道这个函数是什么或做什么;我找到了Do we have a Uncompressed javascript Library for Google Maps API V3

没有未压缩的库。所有 API 方法均根据已发布的文档访问,因此不需要未压缩版本。

是的,没错 - 绝对不需要,当然!当然不是谷歌对他们的财产束手无策——只是没有人需要知道发生了什么,因为不可能遇到这么糟糕的问题:)

无论如何,Firefox 吐出的堆栈跟踪是:

rz.prototype.load http://maps.googleapis.com/maps-api-v3/api/js/26/17/util.js:202:114
qz.prototype.load http://maps.googleapis.com/maps-api-v3/api/js/26/17/util.js:201:427
_.yz.prototype.load http://maps.googleapis.com/maps-api-v3/api/js/26/17/util.js:204:224
dz.prototype.load http://maps.googleapis.com/maps-api-v3/api/js/26/17/util.js:200:287
cz.prototype.load http://maps.googleapis.com/maps-api-v3/api/js/26/17/util.js:199:133
SS http://maps.googleapis.com/maps-api-v3/api/js/26/17/marker.js:5:217
WS http://maps.googleapis.com/maps-api-v3/api/js/26/17/marker.js:7:482
XS http://maps.googleapis.com/maps-api-v3/api/js/26/17/marker.js:7:116
VS.prototype.Y http://maps.googleapis.com/maps-api-v3/api/js/26/17/marker.js:35:646
_.zf.prototype.L/a.F< http://maps.googleapis.com/maps/api/js:112:4221

... Chromium 输出:

util.js:202 Uncaught TypeError: a.url.substr is not a function
rz.load @   util.js:202
cz.load @   util.js:199
oz  @   util.js:6
lz  @   util.js:6
kz.load @   util.js:201
qz.load @   util.js:201
_.yz.load   @   util.js:204
dz.load @   util.js:200
cz.load @   util.js:199
SS  @   marker.js:5
WS  @   marker.js:7
XS  @   marker.js:7
VS.Y    @   marker.js:35
(anonymous function)    @   js?v=3.26&libraries=drawing,geometry:112

所以,显然错误发生在rz.prototype.load,并且是由_.zf.prototype.L/a.F&lt;发起的,即(anonymous function);从 Firefox 信息 (...maps/api/js:112:4221) 中,我将其提取为 _.zf.prototype...:

...
_.zf.prototype.L=function(){
  var a=this;
  a.F||(
        a.F=window.setTimeout(
          function(){
            a.F=void 0; // <=== column:4221 here at ;
            a.Y()
          }
          ,a.ql)
       )
};
...

这是rz.prototype(包含util.js:202:114):

...
rz.prototype.load=function(a,b){
  var c=this.la;
  this.b&&"data:"!=a.url.substr(0,5)||(a=new _.ez(a.url)); // column 114 is right before a.url.substr..
  return c.load(a,function(d){
    !d&&_.m(a.crossOrigin)?c.load(new _.ez(a.url),b):b(d)
  })
};
...

因此,调用者 _.zf.prototype.L 函数执行了 setTimeout 最终调用 rz.prototype,这解释了为什么此错误仅在我按“取消”后一段时间后才显示。

但我的问题是 - 其余代码中的内容是什么,可能称为 _.zf.prototype.L 函数?我怎么能找到那个?如果_.zf.prototype.L 本身是通过setTimeout 调用的,它会“记住”原始调用者/调用堆栈,并且可以检索它以进行调试吗?或者,是否可以设置一个断点,每当一个名为 _.zf.prototype.L 的函数即将被调用时,该断点就会中断?

我尝试查看How to view JavaScript function calls as they occur(其中没有关于如何进行函数调用跟踪的信息);然后找到https://javascriptweblog.wordpress.com/2010/06/01/a-tracer-utility-in-2kb/ - 使用这个库,我可以做到:

tracer.traceAll(BlitzMap,true); 
tracer.traceAll(BlitzMap.getMapObj(),true); 

....但是它跟踪对象功能 OK,地图 obj 有点奇怪(在页面加载时控制台中有 3000+ tracing traceOff 消息)虽然它似乎也跟踪了一些部分 - 但是,当我做我的测试用例时,按下“取消”后,我得到的只是我的代码跟踪(不会崩溃),然后一秒钟过去了,我得到了上面的错误/堆栈跟踪,没有任何其他跟踪。

那么,如何调试这样的问题呢?

【问题讨论】:

    标签: javascript debugging google-maps-api-3


    【解决方案1】:

    好的,我设法解决了这个问题 - 即使接近投票声称问题“过于广泛”。

    首先,如果来自 API 的“前端”javascript 是:

    <script src="http://maps.googleapis.com/maps/api/js?v=3.26&libraries=drawing,geometry" type="text/javascript"></script>
    

    ...然后将其下载到文件中:

    wget "http://maps.googleapis.com/maps/api/js?v=3.26&libraries=drawing,geometry" -O gmapsapi.js
    

    ...并在您的 HTML 中使用此文件而不是在线文件:

    <script src="gmapsapi.js" type="text/javascript"></script>
    

    然后在 Firefox 中打开您的 HTML 文件,让它运行,然后在 Firefox 中执行:文件/将页面另存为/网页,完成。

    这将在本地保存的页面文件夹中下载其他脚本,例如 util.js 等。

    现在,打开 HTML 文件的已保存(作为网页,完整)版本 - 它还应该将脚本的在线链接替换为下载的本地脚本。

    然后,从保存的文件夹中打开gmapsapi.js,并在_.zf.prototype.L函数中引入换行符:

    _.zf.prototype.L=function(){
      var a=this;
      a.F||(a.F=window.setTimeout(function(){a.F=void 0;a.Y()},a.ql))
    };
    

    ...以后可以在一行上设置断点。

    现在,在 Firefox 中打开保存的 HTML 文件,打开 Firebug,在“脚本”选项卡中找到 gmapsapi.js,并在 var a=this; 行设置断点。

    现在运行这些东西——在我的例子中,执行所有操作,包括按下取消——JS 引擎将中断;然后你可以在 Firebug 控制台中做console.trace(),并获得这种跟踪(之后发生错误):

    _.zf.prototype.L()                            gmapsapi.js (line 114)
    VS.prototype.changed(a="modelIcon")           marker.js (line 35)
    Bb(a=Object { type="object"}, b="modelIcon")  gmapsapi.js (line 37)
    Bb(a=Object { type="object"}, b="icon")       gmapsapi.js (line 37)
    _.k.set(a="icon", b=Object { type="object"})  gmapsapi.js (line 96)
    _.vc/<(c=Object { type="object"})             gmapsapi.js (line 47)
    _.k.setValues()                               gmapsapi.js (line 97)
    a = Object { type="object"}
    BlitzMap</this.updateOverlay()                blitz.js (line 545)
    BlitzMap</this.closeInfoWindow()              blitz.js (line 514)
    onclick()input[3] onclick (line 1)
    event = Object { type="object"}
    

    ...确实-这指出了错误所在:即,我攻击了blitz.js并最终为标记的图标写了一个空字符串"",这最终导致了错误。

    这个堆栈跟踪揭示了另外一件事——那就是,为什么这个错误只在我第一次按取消时发生,而不是随后发生;嗯,答案是,错误代码只在VS.prototype.changed(a="modelIcon")时运行,所以第二次设置空字符串不再是“改变”,所以没有错误。

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 1970-01-01
      • 2018-09-14
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 2012-12-03
      • 1970-01-01
      • 2021-06-27
      相关资源
      最近更新 更多