在第三方库中使用异步函数调试JavaScript?

时间:2017-03-01 11:21:19

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

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

blitz-gmaps

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

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< (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,这解释了为什么只有在我按“取消”后一段时间过期后才会显示此错误。 / p>

但我的问题是 - 代码的其余部分是什么,可能会调用此_.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个消息)虽然它似乎也跟踪了一些部分 - 但是,当我执行我的测试用例时,在按下“取消”后,我得到的是我的代码跟踪(不会崩溃),然后一秒钟过去,我得到上面的错误/堆栈跟踪而没有任何其他跟踪。 / p>

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

1 个答案:

答案 0 :(得分: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"}

......确实 - 这指出了bug的位置:即,我已经攻击blitz.js并最终为标记的图标写了一个空字符串"",最终成为了错误的原因。

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