jQuery 函数 $.html() 不等待其他代码行完成

问题描述

我正在尝试从另一个文件中读取数据并在 HTML(更准确地说是 x3d)中使用这些数据。

为了做到这一点,我使用 $.getJSON 读取数据,并使用 $("div").html( "*html code*" ),使用 html 代码中的变量在网站中显示数据。

问题是在$.getJSON读取数据之前执行了*$("div").html( "html code" )*

这是我的代码

<html> 
    <head> 
        <title>Superficie soja 63</title>           
        <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link> 
        
    </head> 

    <body> 
        <h1>Superficie soja 63</h1> 
        
        <div></div>
        <script>
            var a = [];
            var b = [];
            var c = [];
            var tria = [];
            var trib = [];
            var tric = [];
            var str = "";
            var str_tri = "";

            $.getJSON("dados_teste.json",function(data) {
                for(var cont in data.pontos){
                        a.push(data.pontos[cont].x);
                        b.push(data.pontos[cont].y);
                        c.push(data.pontos[cont].z);

                        str += (`${a[cont]} ${b[cont]} ${c[cont]},`);
                }
                str = str.slice(0,-2);
            });

            $.getJSON("tri_teste.json",function(data) {
                for(var cont in data.triangulos){
                    tria.push(data.triangulos[cont].tri_a);
                    trib.push(data.triangulos[cont].tri_b);
                    tric.push(data.triangulos[cont].tri_c);

                    str_tri += (`${tria[cont]} ${trib[cont]} ${tric[cont]},`);
                }
                str_tri = str_tri.slice(0,-2);
            });

        setTimeout(() => {  console.log(str); },1000);
        setTimeout(() => {  console.log(str_tri); },2000);

        $("div").html( ` 

            <x3d width='1000px' height='1000px'> 
                <scene> 
                    <shape> 
                        <appearance>
                            <ImageTexture 
                            url='https://thumbs.dreamstime.com/b/macro-soybean-food-texture-background-top-view-96368287.jpg'/>
                        <TextureTransform
                            translation='0 0'
                            rotation='0'
                            repeats='true'
                            repeatt='true'
                            scale='80 80'/>
                        </appearance>
                        
                        <IndexedTriangleSet 
                            ccw='true' 
                            colorPerVertex='true' 
                            index='${str_tri}'
                            normalPerVertex='true' 
                            solid='false'
                            containerField='geometry'>
                            <Coordinate id="teste"
                                point='${str}'/>
                            <Viewpoint
                                position='0 0 10'
                                orientation=''
                                description='camera'/>
                        </IndexedTriangleSet>
                    </shape> 
                </scene> 
            </x3d> ` )

    </script>

    </body> 
</html>

我已经尝试使用 setTimeout()delay()解决这个问题,但看起来 $.html() 函数会忽略其他函数并且总是先执行。

如果我只是将数据直接分配给变量,它会起作用。问题是我需要读取一个 JSON 文件获取数据。

我该如何解决这个问题?

编辑: 我刚刚发现这个问题只发生在我在 HTML 中使用 X3D 时。 使用普通 HTML, $.html() 工作正常。但是对于 X3D,函数 $.html() 不能正常工作。所以我还在想办法解决这个问题。

解决方法

我尝试使用 javascript 以多种不同方式使此代码工作,并发现问题出在 X3D 上。到目前为止发布的所有答案都有意义,但是当 HTML 代码中包含 X3D 时,它们不起作用。

所以我决定改用 PHP,现在它可以工作了!

<html> 
    <head> 
        <title>Superficie soja 63</title>           
        <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link> 
        
    </head> 

    <body> 
        <h1>Superficie soja 63</h1> 

        <?php
            $path = "dados_teste.json";
            $file = fopen($path,"r");
            $data="";
            while(!feof($file)){
                $data .= fread($file,filesize($path));
            }
            fclose($file);
            $data= json_decode($data,true);
            $str="";
            for($cont=0; $cont < count($data["pontos"]); $cont++){
                if($cont < count($data["pontos"])-1)
                    $str .= ($data["pontos"][$cont]["x"] . " " . $data["pontos"][$cont]["y"] . " " . $data["pontos"][$cont]["z"] . "," );
                else
                    $str .= ($data["pontos"][$cont]["x"] . " " . $data["pontos"][$cont]["y"] . " " . $data["pontos"][$cont]["z"] );
            }
            
            $path = "tri_teste.json";
            $file = fopen($path,true);
            $str_tri="";
            for($cont=0; $cont < count($data["triangulos"]); $cont++){
                if($cont < count($data["triangulos"])-1)
                    $str_tri .= ($data["triangulos"][$cont]["tri_a"] . " " . $data["triangulos"][$cont]["tri_b"] . " " . $data["triangulos"][$cont]["tri_c"] . "," );
                else
                    $str_tri .= ($data["triangulos"][$cont]["tri_a"] . " " . $data["triangulos"][$cont]["tri_b"] . " " . $data["triangulos"][$cont]["tri_c"] );
            }

            echo "
            <x3d width='1000px' height='1000px'> 
                <scene> 
                    <shape> 
                        <appearance>
                            <ImageTexture 
                            url='https://thumbs.dreamstime.com/b/macro-soybean-food-texture-background-top-view-96368287.jpg'/>
                        <TextureTransform
                            translation='0 0'
                            rotation='0'
                            repeats='true'
                            repeatt='true'
                            scale='80 80'/>
                        </appearance>
                        
                        <IndexedTriangleSet 
                            ccw='true' 
                            colorPerVertex='true' 
                            index='${str_tri}'
                            normalPerVertex='true' 
                            solid='false'
                            containerField='geometry'>
                            <Coordinate
                                point='${str}'/>
                            <Viewpoint
                                position='0 0 10'
                                orientation=''
                                description='camera'/>
                        </IndexedTriangleSet>
                    </shape> 
                </scene> 
            </x3d>
            ";
        ?>

    </body> 
</html>

我的结论是:如果您使用 X3D,最好使用后端编程语言。

,

我不是 jQuery 专家,但通过快速查找,我认为您应该在 getJSON 之后尝试 .then() 函数,然后将其余代码写在 then 括号内。 this question

中使用了这样的一个示例

此外,您可以使用 this link 中指定的 .done() 代替 .then()(您必须向下滚动一点才能看到 .done() 示例)

另一种选择是将 $("div").html() 添加到 getJson 回调函数中,如下所示:

 $.getJSON("dados_teste.json",function(data) {
     //your current code
     //you $("div").html() code
 }

让我知道这个答案是否有帮助:)

,

尝试将一项任务的执行时间与另一项任务的开始进行计时称为 race condition,应该避免。而是在收到变量后调用 .html()。因为您有 2 个独立的依赖进程创建变量,所以您只需在 makeDiv() 函数中检查它们。

var str,str_tri
 $.getJSON("dados_teste.json",function(data) {
               ...
                str = str.slice(0,-2);
                makeDiv();
            });
 $.getJSON("tri_teste.json",function(data) {
               ...
                str_tri = str_tri.slice(0,-2);
                makeDiv();
            });


function makeDiv() {
 if (!str || !str_tri || str =='' || str_tri == '') return;
 $("div").html( `......`);
}