使用 Chrome 开发工具调试异步 JavaScript(Debugging Asynchronous JavaScript with Chrome DevTools)

简介: 使用 Chrome 开发工具调试异步 JavaScript太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)本文遵循“署名-非商业用途-保持一致”创作公用协议转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。

使用 Chrome 开发工具调试异步 JavaScript

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载,谢谢合作。



终于又发现一个值得研究的领域,一头雾水,继续研究,估计研究明白了,也就能翻译明白了,也算是一种推动力吧。

FireFox 的调试功能居然把 16G 内存 Mac Mini 给卡死了,看来还得用 Chrome,虽然其调试的断点总是对不到正确的代码上去,也许还是用得不对吧!

十几年前,做 Web 开发时,感觉 JS 已经很熟了,有一些规律,虽然说不出来,但对于问题的查找与排除很有效,时隔多年,全然就饭吃了。

幸好有这些个调试工具,真心得用好它们,才能尽快找出问题。

当下 html5 盛行,单个页面的背后异步活动越来越多,没有这种调试工具的配合,也确实难以应对。

这种无节制的隐藏于页面背后的活动,是否会将 flash 在页面上泛烂的情况,掩藏到页面背后去呢?

这个确实值得关注......


内容列表
Table of Contents

Localizations

使用 Chrome 开发工具调试异步 JavaScript
Debugging Asynchronous JavaScript with Chrome DevTools


入门
Introduction

使 JavaScript 独一无二的一个强大特性就是它的通过回调函数异步工作的能力。设定异步回调可以让你编写事件驱动代码,但它也使得跟踪问题变得一头雾水,因为 JavaScript 不是线性执行的。
A powerful feature that makes JavaScript unique is its ability to work asynchronously via callback functions. Assigning async callbacks let you write event-driven code but it also makes tracking down bugs a hair pulling experience since the JavaScript is not executing in a linear fashion.

Luckily, now in Chrome Canary DevTools, you can view the full call stack of asynchronous JavaScript callbacks!

A quick teaser overview of async call stacksA quick teaser overview of async call stacks.

(We'll break down the flow of this demo soon.)

Once you enable the async call stack feature in DevTools, you will be able to drill into the state of your web app at various points in time. Walk the full stack trace for event listeners, setIntervalsetTimeoutXMLHttpRequest, promises,requestAnimationFrameMutationObservers, and more.

As you walk the stack trace, you can also analyze the value of any variable at that particular point of runtime execution. It's like a time machine for your watch expressions!

Let's enable this feature and take a look at a few of these scenarios.

Enable async debugging in Chrome Canary

Try out this new feature by enabling it in Chrome Canary (build 35 or higher). Go to the Sources panel of Chrome Canary DevTools.

Next to the Call Stack panel on the right hand side, there is a new checkbox for "Async". Toggle the checkbox to turn async debugging on or off. (Although once it's on, you may not ever want to turn it off.)

Toggle the async feature on or off

Capture delayed timer events and XHR responses

You've probably seen this before in Gmail:

Gmail retrying to send an email

If there is a problem sending the request (either the server is having problems or there are network connectivity issues on the client side), Gmail will automatically try re-sending the message after a short timeout.

To see how async call stacks can help us analyze delayed timer events and XHR responses, I've recreated that flow with a mock Gmail example. The full JavaScript code can be found in the link above but the flow is as follows:

Flow chart of mock Gmail exampleIn the diagram above, the methods highlighted in blue are prime spots for this new DevTool feature to be the most beneficial since these methods work asynchronously.

By solely looking at the Call Stack panel in previous versions of DevTools, a breakpoint within postOnFail() would give you little information about wherepostOnFail() was being called from. But look at the difference when turning on async stacks:

Before Breakpoint set in mock Gmail example without async call stacksThe Call Stack panel  without async enabled. 

Here you can see that postOnFail() was initiated from an AJAX callback but no further info.

After Breakpoint set in mock Gmail example with async call stacksThe Call Stack panel  with async enabled. 

Here you can see that the XHR was initiated fromsubmitHandler(), which was initiated from a click handler bound from scripts.js. Nice!

With async call stacks turned on, you can view the entire call stack to easily see if the request was initiated from submitHandler() as it was above, or fromretrySubmit() as it is below:

Another breakpoint set in mock Gmail example with async call stacks

From the Call Stack panel, you can also tell if the breakpoint event originated earlier from an UI event like 'click', a setTimeout() delay, or any commonly used async callback event.

Watch expressions asynchronously

When you walk the full call stack, your watched expressions will also update to reflect the state that it was in at that time!

An example of using watch expressions with aysnc call stacks

Evaluate code from past scopes

In addition to simply watching expressions, you can interact with your code from previous scopes right in the DevTools JavaScript console panel.

Imagine that you are Dr. Who and you need a little help comparing the clock from before you got into the Tardis to "now". From the DevTools console, you can easily evaluate, store, and do calculations on values from across different execution points.

An example of using the JavaScript console with aysnc call stacksUse the JavaScript console in conjunction with async call stacks to debug your code. The above demo can be found  here.

Staying within DevTools to manipulate your expressions will save you time from having to switch back to your source code, make edits, and refresh the browser.

Coming soon: Unravel chained promise resolutions

If you thought the previous mock Gmail flow was hard to unravel without the async call stack feature enabled, can you imagine how much harder it would be with more complex asynchronous flows like chained promises? Let's revisit the final example of Jake Archibald's tutorial on JavaScript Promises.

Flow diagram from  JavaScript Promises.

Here's a little animation of walking the call stacks in Jake's async-best-example.html example.

Before Breakpoint set in promises example without async call stacksThe Call Stack panel  without async enabled. 

Notice how the Call Stack panel is pretty short on info when trying to debug promises.

After Breakpoint set in promises example with async call stacksThe Call Stack panel  with async enabled. 

Wow! Such promises. Much callbacks.

Promise support for call stacks will be ready soon, as the promise implementation is switching from the version in Blink to the final one within V8.

In the spirit of walking back in time, if you want to preview async call stacks for promises today, you can check it out in Chrome 33 or Chrome 34. Go tochrome://flags/#enable-devtools-experiments and enable Developer Tools experiments . After you restart Canary, go to the DevTools settings and there will be an option to enable support for async stack traces.

Get insights into your web animations

Let's go deeper into the HTML5Rocks archives. Remember Paul Lewis' Leaner, Meaner, Faster Animations with requestAnimationFrame?

Open up the requestAnimationFrame demo and add a breakpoint at the beginning of the update() method (around line 874) of post.html. With async call stacks we get a lot more insights into requestAnimationFrame. And, much like the mock Gmail example, we get to walk all the way back to the initiating event which was a 'scroll' event.

Before Breakpoint set in requestAnimationFrame example without async call stacksThe Call Stack panel  without async enabled.After Breakpoint set in requestAnimationFrame example with async call stacksAnd  with async enabled.

Track down DOM updates when using MutationObserver

MutationObserver allow us to observe changes in the DOM. In this simple example, when you click on the button, a new DOM node is appended to<div class="rows"></div>.

Add a breakpoint within nodeAdded() (line 31) in demo.html. With async call stacks enabled, you can now walk the call stack back through addNode() to the initial click event.

Before Breakpoint set in mutationObserver example without async call stacksThe Call Stack panel  without async enabled.After Breakpoint set in mutationObserver example with async call stacksAnd  with async enabled.

Tips for debugging JavaScript in async call stacks

Name your functions

If you tend to assign all of your callbacks as anonymous functions, you may wish to instead give them a name to make viewing the call stack easier.

For example, take an anonymous function like this:

window.addEventListener('load', function(){
  // do something
});

And give it a name like windowLoaded():

window.addEventListener('load', function windowLoaded(){
  // do something
});

When the load event fires, it will show up in the DevTools stack trace with its function name instead of the cryptic "(anonymous function)". This makes it much easier to see at a glance what's happening in your stack trace.

Before An anonymous functionAfter A named function

Explore further

To recap, these are all the asynchronous callbacks in which DevTools will display the full call stack:

  • Timers: Walk back to where setTimeout() or setInterval() was initialized.
  • XHRs: Walk back to where xhr.send() was called.
  • Animation frames: Walk back to where requestAnimationFrame was called.
  • Event listeners: Walk back to where the event was originally bound with addEventListener().
  • MutationObservers: Walk back to where the mutation observer event was fired.

Full call stacks will be coming soon for these experimental JavaScript APIs:

  • Promises: Walk back to where a promise has been resolved.
  • Object.observe: Walk back to where the observer callback was originally bound.

Being able to see the full stack trace of your JavaScript callbacks should keep those hairs on your head. This feature in DevTools will be especially helpful when multiple async events happen in relation to each other, or if an uncaught exception is thrown from within an async callback.

Give it a try in Chrome Canary. If you have feedback on this new feature, drop us a line on the Chrome DevTools Group or file a bug in the Chrome DevTools bug tracker.




目录
相关文章
|
4月前
|
Web App开发 JavaScript 前端开发
chrome调试秘籍,让你的开发速度飞起来
chrome调试秘籍,让你的开发速度飞起来
|
2月前
|
Web App开发 前端开发 JavaScript
控制台出现报错DevTools failed to load source map: Could not load content for chrome-extension://的原因及解决方案
控制台出现报错DevTools failed to load source map: Could not load content for chrome-extension://的原因及解决方案
58 0
控制台出现报错DevTools failed to load source map: Could not load content for chrome-extension://的原因及解决方案
|
10天前
|
JavaScript 前端开发 开发者
JavaScript基础入门之浏览器控制台调试输出
本文章是对小白学习js的初级教程,也是我对自己学习经验的一种总结,文章大多采用使用案例加讲解,带动学习的方式.因为我们的天性总是喜欢有及时反馈的事物,但是学习是一个慢长的事情,而有结果的回应,才会更好的促进自己去学习,主要是对于javascript学习中的输出,有个大体上的了解,同时通过教学能够更好的使用浏览器来方便我们去学习和运行代码,也是对自己进行笔记整理,对抓住信息关键点的一种提高.
|
14天前
|
Web App开发 前端开发 JavaScript
【专栏:工具与技巧篇】网页调试工具(Chrome DevTools)的使用
【4月更文挑战第30天】Chrome DevTools是谷歌浏览器内置的网页调试利器,提供Elements(查看编辑HTML/CSS)、Console(JavaScript调试)、Sources(JS/CSS文件调试)、Network(网络请求分析)和Performance(性能瓶颈排查)等面板。通过掌握这些功能,开发者能有效优化网页性能和用户体验。本文详细介绍了各面板的使用方法,助力开发者高效工作。
|
14天前
|
前端开发 JavaScript 开发者
【JavaScript技术专栏】JavaScript错误处理与调试技巧
【4月更文挑战第30天】JavaScript开发中的错误处理和调试至关重要。语言提供三种错误类型:语法错误、引用错误和类型错误。为处理错误,可以使用`try...catch`捕获异常,`throw`语句显式抛出错误,以及`Error`对象创建自定义错误。调试技巧包括使用`console.log`、设置断点、利用源映射和性能分析。这些方法能帮助开发者高效定位和解决问题,提高代码质量。
|
15天前
|
Web App开发 JavaScript 前端开发
【专栏】如何使用 Chrome DevTools 的断点功能提升前端调试效率, 花式打断点
【4月更文挑战第29天】本文介绍了如何使用 Chrome DevTools 的断点功能提升前端调试效率。从基本的行断点和函数断点,到更高级的条件断点、DOM 断点、XHR 断点和事件断点,以及代码注入断点,详细阐述了各种断点的设置和应用场景。通过断点调试实战案例,如异步操作、复杂逻辑和性能优化,展示断点在解决实际问题中的重要作用。掌握这些技巧能有效提高开发质量和效率。
|
4月前
|
Web App开发 前端开发 JavaScript
超实用的Chrome DevTools调试技巧
超实用的Chrome DevTools调试技巧
|
1月前
|
监控 前端开发 JavaScript
如何在浏览器中使用javaScript进行代码调试
【4月更文挑战第11天】在浏览器中调试JavaScript是前端开发的关键技能。使用开发者工具(可通过F12、右键检查或菜单栏访问),遵循以下步骤:1) 打开Sources标签页查看所有脚本;2) 设置断点在需要暂停的代码行;3) 刷新页面触发断点;4) 利用调试工具如Scopes、Watch、Call Stack等检查代码状态;5) 使用Console辅助调试;6) 利用其他工具如Network、Performance和Memory进行性能分析。确保使用最新工具,保持代码清晰,以提升调试效率。
53 4
|
2月前
|
Web App开发 前端开发 JavaScript
防止你的 Web 应用被别人通过 Chrome 开发者工具进行调试的一种简单办法
防止你的 Web 应用被别人通过 Chrome 开发者工具进行调试的一种简单办法
31 0
|
3月前
|
JavaScript 开发者
JS逆向 -- 本地调试
JS逆向 -- 本地调试
16 0