
我在学习 chrome 插件开发的过程中遇到一个问题,代码如下:
(function(){ var protocol = window.location.protocol; var host = window.location.host; var href = window.location.href; var source = document.getElementsByTagName('html')[0].innerHTML; var target_list = []; var js_result = []; var source_href = source.match(/href=['"].*?['"]/g); var source_src = source.match(/src=['"].*?['"]/g); var script_src = source.match(/<script [^><]*?src=['"].*?['"]/g); if(source_href){ for(var i=0;i<source_href.length;i++){ var u = deal_url(source_href[i].substring(6,source_href[i].length-1)); if(u){ target_list.push(u); } } } if(source_src){ //var js_result = []; for(var i=0;i<source_src.length;i++){ var u = deal_url(source_src[i].substring(5,source_src[i].length-1)); if(u){ target_list.push(u); var xhr = new XMLHttpRequest(); xhr.open("GET", u, true); xhr.send(); xhr.Onreadystatechange= function() { var src = this.responseText; var script_url = src.match(/( https?|http|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g); if(script_url){ for(var t=0;t<script_url.length;t++){ var y = script_url[t]; if(y){ js_result.push(y); } } } } } } } console.log(js_result) console.log(target_list) 问题是: console 打印出来的 js_result 和 target_list 是不同形式的(就好像一个数组是空的,一个数组包含了值), 如图:

点开空的那个, 就能看到结果,但是没有直接显示出来 
1 RaDisH7 2023-04-29 15:20:58 +08:00 因为你的 xhr 请求是异步的,可以去了解一下 Javascript 的异步、同步、promise 这些东西 https://zh.Javascript.info/async |
3 fu4k OP 感觉 promise 、await 、async 理解起来好难 |
4 fu4k OP 有没有好心人能给出 code 示例 |
5 turan12 2023-04-29 19:46:57 +08:00 xhr.open("GET", u, true) 改为 xhr.open("GET", u, false) ,就创建了一个同步请求 |
6 huijiewei 2023-04-29 19:52:38 +08:00 @fu4k 很好理解啊。异步就是数据只能在 callback 里面取到,promise 就是承诺给你数据,要在 then 里面处理,async/await 就是异步转为同步代码 |
9 Yukiteru 2023-04-29 21:15:06 +08:00 可以用 fetch 啊,然后 await |
10 huijiewei 2023-04-29 21:15:52 +08:00 @fu4k 付什么费。js_result 只有在 xhr.onreadystatechange 的方法里面才是真正的数据 |
11 huijiewei 2023-04-29 21:16:41 +08:00 onreadystatechange 就是 xhr 的一个 callback 。 |
12 stefanieewu 2023-04-29 21:31:02 +08:00 如果你不想改现在代码结构的话,就在 xhr 的回调里面判断拿了多少条请求结束的结果,然后判断长度是不是超过了 soucre_src 数组的长度,如果超过,说明所有发出的请求都结束了(不管成功失败)这时候打印 if (source_src) { //var js_result = []; let index = 0; let callbackFun = () => { console.log(js_result) console.log(target_list) } // ...其他代码 xhr.Onreadystatechange= () => { // 最后新加 index++; if (index >= source_src.length) { // 执行所有请求结束的回调 // callback() callbackFun() } } } 当然是建议用 promise + promise.all 去写,或者用 fetch ; 如果有其他问题,可以加我 vx:bGlqaWF0dTE5OTg= |
14 lneoi 2023-04-29 22:46:22 +08:00 没看太懂问题是什么。 console 打印对象时也是引用的,打印语句执行的时候对象是空的,所以预览信息里面就是空的。当点开后会去读取最新的内容,刚好你这变量异步请求后会更新值,所以点开后会后跟预览不一样的信息。 |
16 7gugu 2023-04-30 18:17:47 +08:00 直接在对应的位置输入“debug”,直接打断点就能看到对应的变量值了 |