iT邦幫忙

1

我有多個api
差別只有後面測站不同
然後想要同時顯示在相對應的測站表格上
我是想用迴圈來去抓每個api裡的資料

下面是我的程式碼

<script>
        var x = new Array();
        var t = 0;
        var device_id = ["74DA38E2B4CA", "74DA38B05396"]
        for (j in device_id) {
            var openUrl = "https://pm25.lass-net.org/data/last.php?device_id=" + device_id[j];

            var xhr = new XMLHttpRequest();
            xhr.open('GET',openUrl, true);
            xhr.send();
            xhr.onload = function  () {
                if (this.readyState === 4 && this.status === 200) {
                    var data = JSON.parse(this.responseText);

                    x += "<p> 測站:  " + data.feeds[0].AirBox.name + "<br>";
                    x += "<p> 濕度:  " + data.feeds[0].AirBox.s_h0 + "<br>";
                    

                    if (device_id[j]=="74DA38E2B4CA"){
                        document.getElementById("74DA38E2B4CA").innerHTML = x;
                        x="";
                    }
                    else if (device_id[j]=="74DA38B05396"){
                        document.getElementById("74DA38B05396").innerHTML = x;
                        x="";
                    }
                }         
            };
        }
   </script>
</head>

<body>
    <p id="74DA38E2B4CA"></p>
    <p id="74DA38B05396"></p>
    <p id="demo"></p>
</body>

</html>

現在的問題是因為onload只會執行最後一筆資料
所以我前面的資料都不會回傳
想請問有哪一個方法可以修改?

看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2020-03-10 05:54:50 檢舉
https://www.runoob.com/jsref/met-win-setinterval.html
你需要這個吧?
listennn08 iT邦研究生 3 級 ‧ 2020-03-10 08:35:17 檢舉
var x = new Array();
x += "<p> 測站: " + data.feeds[0].AirBox.name + "<br>";
陣列是這樣用的嗎@@

j 前面加個 let 應該就可以了
froce iT邦大師 1 級 ‧ 2020-03-10 09:30:15 檢舉
js就是這樣神奇的還是可以跑...Orz
fillano iT邦超人 1 級 ‧ 2020-03-10 10:12:38 檢舉
建議:for迴圈裡面的程式放到一個函數裡面,把j傳給這個函數。你的問題不只是j...簡單說,用函數包起來可以解決迴圈裡面發生的scope問題。
淺水員 iT邦新手 1 級 ‧ 2020-03-10 11:02:10 檢舉
雖然跟發問的問題關係不大,xhr.send 建議放 xhr.onload 後面比較好。

2 個回答

2
淺水員
iT邦新手 1 級 ‧ 2020-03-10 11:34:45

提供參考,改動處大概是:

  1. 如 fillano 所說放到 function 裡面處理(這邊就順便用 Array.forEach 了)。
  2. 既然 device_id[j] 就是 <P> 的 id ,就直接把 device_id[j] 代入 getElementById 就可以了,不用再用 if 判斷。
  3. 考慮到遠端抓的資料直接作為 innerHTML 的內容可能會產生問題,多加了一個過濾函式。
  4. 把 xhr.send 挪到 xhr.onload 後面。
//filterHTML 函式可以跳脫 html 特殊字元
//以避免抓來的資料有 "<" 或 ">" 等字元造成顯示錯誤
var filterHTML=(function(){
    var span=document.createElement('span');
    return function(str) {
        span.textContent=str;
        return span.innerHTML;
    }
})();

var device_id = ["74DA38E2B4CA", "74DA38B05396"];
device_id.forEach(function(id){
    var openUrl = "https://pm25.lass-net.org/data/last.php?device_id=" + id;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', openUrl, true);
    xhr.onload = function  () {
        if (this.readyState === 4) {
            if (this.status === 200) {
                var data = JSON.parse(this.responseText);
                var name = filterHTML(data.feeds[0].AirBox.name);
                var s_h0 = filterHTML(data.feeds[0].AirBox.s_h0);
                document.getElementById(id).innerHTML=
                    "<p> 測站:  " + name + "</p>"+
                    "<p> 濕度:  " + s_h0 + "</p>";
            } else {
                document.getElementById(id).innerHTML='error (' + id + ')';
            }
        }
    };
    xhr.send();
});
lingwu iT邦新手 5 級 ‧ 2020-03-10 23:12:42 檢舉

感謝幫忙解釋!!

1
Zoey
iT邦新手 5 級 ‧ 2020-03-12 16:25:59

使用了listennn08說的方式,把for (j in device_id)修改為for (let j in device_id)
測試成功
程式碼如下

 var device_id = ["74DA38E2B4CA", "74DA38B05396"]
        for (let j in device_id) {
            var openUrl = "https://pm25.lass-net.org/data/last.php?device_id=" + device_id[j];

            var xhr = new XMLHttpRequest();
            xhr.open('GET', openUrl, true);
            xhr.send();
            xhr.onload = function () {
                if (this.readyState === 4 && this.status === 200) {
                    var data = JSON.parse(this.responseText);
                    document.getElementById(device_id[j]).innerHTML =
                        `<p> 測站: ${data.feeds[0].AirBox.name}</p>
                         <p> 濕度: ${data.feeds[0].AirBox.s_h0}</p>`;
                }else{
                    document.getElementById(device_id[j]).innerHTML = `error:${device_id[j]}`
                }
            };
        }

我要發表回答

立即登入回答