随着浏览器的逐渐强大,绝大多数情况下的代码调试都是可以通过浏览器自带的一些调试工具进行解决。然而对于一些特殊情况仍然无法享受到浏览器的强大 调试能力,比如QQ客户端内嵌web的调试(虽然说QQ目前已经可以编译开发者工具,但是仍需要安装指定文件包或工具)、非正常浏览器web、移动场景下 的内嵌等场景。

 

随着浏览器的逐渐强大,绝大多数情况下的代码调试都是可以通过浏览器自带的一些调试工具进行解决。然而对于一些特殊情况仍然无法享受到浏览器的强大 调试能力,比如QQ客户端内嵌web的调试(虽然说QQ目前已经可以编译开发者工具,但是仍需要安装指定文件包或工具)、非正常浏览器web、移动场景下 的内嵌等场景。 基于这个场景我们团队已经在nohost下引入了weinre,并得到了广泛的使用。 但是weinre是有一定的局限性,只能做到console.log和DOM查看等,不能支持断点调试。这里之前老文章已经有过一些描述,可参见 http://www.webryan.net/2013/04/talk-about-remote-debugging-on-mobile-phone/

本文重点讲解不依赖浏览器控制台能力,单纯通过JavaScript方式来实现断点调试的能力,为大家解决问题提供另一种思路和方法。首先会给出工具的使用方法,让大家有感性认识,然后再讲解具体实现原理。

【测试使用】

1、cmd命令下执行”npm install breakpoint -g”(npm安装不赘述,-g为了全局安装且注册bin命令)
2、cmd命令行下执行”breakpoint”(会给出使用帮助,并默认启动测试目录:可以直接通过URL访问);
3、开启两个现代浏览器如chrome和safari,分别打开提示的两个URL。

好了,简单三步就可以在浏览器里测试了。这个ui/index.html操作方法如下:

是不是很简单:),下面我们来给出实战例子;

【实战使用】

【参数说明】

Usage: breakpoint -d htdocsDir -r passbyRule

-d 指定本地静态目录,这里的HTML文件head里会被注入调试脚本。

-r 指定透传规则,通常用于将CGI请求透传给现网服务器;如果是需要透传给指定服务器,则需要在本地hosts文件中做一下指向;

-h 当存在多网卡的情况下,可以使用-h指定某一IP;

breakpoint执行后会在本地启用3个端口,80(用于提供访问服务)、8000(用于控制器)、8500(用于文件重写);

【实战举例】

假设我们域名是:abc.com;本地静态文件(HTML、CSS和JS等)目录是:e:\svn\trunk\htdocs\,那么可以通 过”breakpoint -d e:\svn\trunk\htdocs”将所有的请求转发到本地目录,比如:http://abc.com/a.html会返回本地目录e:\svn \trunk\htdocs\a.html的内容。

但是此时直接在浏览器中访问abc.com是不行的,需要先通过fiddler等工具将abc.com指向本地IP(参考Step 1的)。

然后再访问 http://10.64.53.85:8000/ui/index.html 打开控制器;访问: http://abc.com/a.html 访问资源内容。

不难发现,访问内容已经成功走了本地,且自动在头部加上了调试脚本,这就搞定了。

但是往往调试的时候,我们又希望某些文件访问现网资源或者其他服务器的资源,这个时候,可以通过-r参数来正则匹配放过对应的请求。比 如:abc.com指向本地IP后,希望abc.com/cgi-bin/下的所有请求都发送到现网。 那么只需要执行”breakpoint -d e:\svn\trunk\htdocs\ -r cgi-bin”即可。

【原理分析】

如何通过JavaScript来实现断点调试?

断点调试的核心问题就是要让脚本在某行代码暂停执行,那么Aleksander Kmetec同学给出的解决方案是:通过在每行JavaScript前面加一个断点函数。而断点函数是 通过AJAX的同步属性来阻塞浏览器

那么JavaScript修改前后的情况如下:

修改前 修改后

var a = 1;

var b =2;

function test(){

var c = ‘init’;

c=’change’;

}

Break();var a = 1;

Break();var b =2;

Break(); function test(){

Break(); var c = ‘init’;

Break(); c=’change’;

}

这样通过break函数里发起同步AJAX请求即可确定断点位置和阻塞浏览器执行后面的脚本了,真是很聪明的做法。

【breakpoint结构图】

1、通过浏览器发起网页请求;

2、请求通过fiddler等方式指向到我们的重写服务,重写服务根据请求链接来处理流程。如果是匹配了-r的正则规则,则直接转发到现网服务器,否则则请求本地-d目录下的内容。

3、透传的内容直接不处理,其他的内容会判断:1、HTML文件则会默认在head第一行加入调试脚本的script(该脚本包括调试所需要的方法,如break();) 2、JS文件则会在每一行脚本前增加break();函数的调用。

4、重写服务返回数据给浏览器

5、当浏览器执行JS的时候,会先遇到break();则发起同步的XHR请求,阻塞住浏览器的执行。

6、如果通过调试服务UI界面设置过断点,调试服务则会hold住在break()里的XHR请求,直到调试服务UI发出新的命令(比如跳过、下一行等)

不依赖浏览器控制台的JavaScript断点调试方法的更多相关文章

  1. MyEclipse断点调试方法

    MyEclipse断点调试方法 最基本的操作是: 1, 首先在一个java文件中设断点,然后运行,当程序走到断点处就会转到debug视图下, 2, F5键与F6键均为单步调试,F5是step into ...

  2. Intellij IDEA 创建控制台项目,断点调试

    在idea 2016中创建一个控制台项目(经常会忘) 打开创建界面 注意,什么都不要选,点击next(最坑的地方,经常忘) 再次点击next ============================= ...

  3. Intellij IDEA 创建控制台项目,断点调试快捷方式

    在idea 2016中创建一个控制台项目(经常会忘) 打开创建界面 注意,什么都不要选,点击next(最坑的地方,经常忘) 再次点击next ============================= ...

  4. JavaScript常见调试方法

    编辑导语:javascript调试方法,常见使用alert和console来定位出错和输出的结果是否是想要的,在chrome中,还可以使用断点来看运行的情况等,本文介绍了比较全面的调试方法,你知道co ...

  5. javascript代码 调试方法

    你的代码可能包含语法错误,逻辑错误,如果没有调试工具,这些错误比较难于发现. 通常,如果 JavaScript 出现错误,是不会有提示信息,这样你就无法找到代码错误的位置. 在程序代码中寻找错误叫做代 ...

  6. vscode中php断点调试方法!

    一.PHP的代码断点调试 1.打开vscode的首选项设置,添加"php.validate.executablePath": "D:\\newXampp\\php\\ph ...

  7. Eclipse断点调试方法

    1. 条件断点 断点大家都比较熟悉,在Eclipse Java 编辑区的行头双击就会得到一个断点,代码会运行到此处时停止. 条件断点,顾名思义就是一个有一定条件的断点,只有满足了用户设置的条件,代码才 ...

  8. Drools mvel方言drl断点调试方法

    开发环境:myeclipse2014,  jdk1.8.0.91,drools6.4.0.Final, drools-eclipse-plugin,mvel2-2.2.6.Final问题描述:drl使 ...

  9. c语音 dll断点调试方法

    转自:https://blog.csdn.net/qingzai_/article/details/45348613 dll调试方法: 1.把最新生成的dll和pdb放到 启动这个dll 的进程目录下 ...

随机推荐

  1. java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

    下面是我查询数据库时打印出来的异常信息: ### Error querying database.  Cause: java.sql.SQLException: Value '0000-00-00 0 ...

  2. 数位dp初步——数位dp的两种方式

    数位dp:一类统计区间[L,R]内某种符合规定的数字个数的题目.特征是R的范围会很大,O(N)范围内无法完成. 一般而言,解决这类题目有两种方式,一种是递推,另一种是记忆化搜索. 递推: 1)利用dp ...

  3. [SinGuLaRiTy] 字节大小

    [SinGuLaRiTy-1006] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 16位编译器 char 1个字节 char*(即指针变量 ...

  4. 老李推荐:第5章3节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动脚本

    老李推荐:第5章3节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动脚本   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性 ...

  5. Android 微信第三方登录

    步骤一 微信开发者平台 我开始的解决思路是,去微信开发者平台看API文档. 这个API文档的主要意思呢,有三点: 1.你得下载这几样东西(下载链接),一个是他的范例代码,一个是他的签名生成工具. 2. ...

  6. Java中执行shell笔记

    在java中执行shell有好几种方式:第一种(exec)方式一 public static synchronized void runshell2() {    File superuser = n ...

  7. java 基础知识九 类与对象

    java  基础知识九  类与对象 1.OO(Object–Oriented )面向对象,OO方法(Object-Oriented Method,面向对象方法,面向对象的方法)是一种把面向对象的思想应 ...

  8. es6基础系列一:let和const

    let 声明变量,可以说是具有作用域的var,用于声明变量,主要规则如下: 1 let声明的变量拥有块级作用域 { let i = 1; console.log(i); // 1 } console. ...

  9. weex里Vuex state使用storage持久化

    在weex里使用Vuex作为state管理工具,问题来了,如何使得state可以持久化呢?weex官方提供store模块,因此我们可以尝试使用该模块来持久化state. 先看下该模块介绍: stora ...

  10. 浩哥解析MyBatis源码(十)——Type类型模块之类型处理器

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6715063.html 1.回顾 之前的两篇分别解析了类型别名注册器和类型处理器注册器,此二 ...