V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
fu4k
V2EX  ›  问与答

求解答一个前端问题

  •  
  •   fu4k · 2023-04-29 15:09:36 +08:00 · 1552 次点击
    这是一个创建于 575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在学习 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 是不同形式的(就好像一个数组是空的,一个数组包含了值), 如图:

    图片

    点开空的那个▶️, 就能看到结果,但是没有直接显示出来 图片

    16 条回复    2023-04-30 18:17:47 +08:00
    RaDisH7
        1
    RaDisH7  
       2023-04-29 15:20:58 +08:00   ❤️ 1
    因为你的 xhr 请求是异步的,可以去了解一下 JavaScript 的异步、同步、promise 这些东西 https://zh.javascript.info/async
    fu4k
        2
    fu4k  
    OP
       2023-04-29 15:26:33 +08:00
    @RaDisH7 谢谢大哥 悟了 我去试试
    fu4k
        3
    fu4k  
    OP
       2023-04-29 17:42:25 +08:00
    感觉 promise 、await 、async 理解起来好难🤯
    fu4k
        4
    fu4k  
    OP
       2023-04-29 19:12:56 +08:00
    有没有好心人能给出 code 示例🙏
    turan12
        5
    turan12  
       2023-04-29 19:46:57 +08:00
    xhr.open("GET", u, true) 改为 xhr.open("GET", u, false) ,就创建了一个同步请求
    huijiewei
        6
    huijiewei  
       2023-04-29 19:52:38 +08:00
    @fu4k 很好理解啊。异步就是数据只能在 callback 里面取到,promise 就是承诺给你数据,要在 then 里面处理,async/await 就是异步转为同步代码
    fu4k
        7
    fu4k  
    OP
       2023-04-29 20:25:49 +08:00
    @turan12 同步请求会有很多异常阻塞 qwq..
    fu4k
        8
    fu4k  
    OP
       2023-04-29 21:05:12 +08:00
    付费求大佬赐教😭
    @RaDisH7 @huijiewei @turan12
    Yukiteru
        9
    Yukiteru  
       2023-04-29 21:15:06 +08:00
    可以用 fetch 啊,然后 await
    huijiewei
        10
    huijiewei  
       2023-04-29 21:15:52 +08:00
    @fu4k 付什么费。js_result 只有在 xhr.onreadystatechange 的方法里面才是真正的数据
    huijiewei
        11
    huijiewei  
       2023-04-29 21:16:41 +08:00
    onreadystatechange 就是 xhr 的一个 callback 。
    stefanieewu
        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=
    fu4k
        13
    fu4k  
    OP
       2023-04-29 21:32:19 +08:00
    @Yukiteru fetch 试了,会有同源问题
    lneoi
        14
    lneoi  
       2023-04-29 22:46:22 +08:00
    没看太懂问题是什么。
    console 打印对象时也是引用的,打印语句执行的时候对象是空的,所以预览信息里面就是空的。当点开后会去读取最新的内容,刚好你这变量异步请求后会更新值,所以点开后会后跟预览不一样的信息。
    fingers
        15
    fingers  
       2023-04-30 10:14:29 +08:00 via iPhone
    @lneoi 感谢回复 问题是想在预览的时候就打印出结果
    12 楼老哥已经帮忙解决了问题,谢谢大家
    7gugu
        16
    7gugu  
       2023-04-30 18:17:47 +08:00
    直接在对应的位置输入“debug”,直接打断点就能看到对应的变量值了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1390 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:14 · PVG 01:14 · LAX 09:14 · JFK 12:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.