iT邦幫忙

0

使用$.ajax()載入資料,並整理變成另一個物件,但不知道為什麼載入的資料沒辦法帶入函式使用?跑不出東西!

各位大大好,在下前端新手想請教一下,透過$.ajax()使用政府中央氣象局開放的API載入資料,但載入下來的資料似乎無法帶入函式使用,但使用自己手動新增的資料就可以,相關資料如下圖:

---透過$.ajax()載入的資料
let api_url="https://opendata.cwb.gov.tw/api/v1/rest/datastore/"
let place_id="F-D0047-089"
let authorization="Authorization=CWB-562E7CFF-0F60-4C07-B56D-91D6227CA2E5"
let element="&elementName=PoP6h"
var data=[]
$.ajax({
  type: "GET",
  url: api_url+place_id+"?"+authorization+element,
  success: function(res){
    let obj=res.records.locations[0].location[0].weatherElement[0].time
    data=obj
  },
   error: function (thrownError) {
      console.log(thrownError);
    }
})
---自己手動新增的資料
var data=[
  {
    "startTime": "2021-01-20 18:00:00",
    "endTime": "2021-01-21 06:00:00",
    "elementValue": [
      {
        "value": "0",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-21 06:00:00",
    "endTime": "2021-01-21 18:00:00",
    "elementValue": [
      {
        "value": "10",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-21 18:00:00",
    "endTime": "2021-01-22 06:00:00",
    "elementValue": [
      {
        "value": "20",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-22 06:00:00",
    "endTime": "2021-01-22 18:00:00",
    "elementValue": [
      {
        "value": "50",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-22 18:00:00",
    "endTime": "2021-01-23 06:00:00",
    "elementValue": [
      {
        "value": "30",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-23 06:00:00",
    "endTime": "2021-01-23 18:00:00",
    "elementValue": [
      {
        "value": "30",
        "measures": "百分比"
      }
    ]
  },
  {
    "startTime": "2021-01-23 18:00:00",
    "endTime": "2021-01-24 06:00:00",
    "elementValue": [
      {
        "value": "0",
        "measures": "百分比"
      }
    ]
  }
]

代入的函式如下:

var new_data=[]
//進行資料處理,另存成一個新陣列
function generate_data(data){
  var new_obj = new Object()
  for(let i=0;i<data.length;i++){
    var date=d3.timeParse("%Y-%m-%d %H:%M:%S")(data[i].startTime)
    new_obj['time'] =date
    new_obj['value'] = data[i].elementValue[0].value
    new_data.push(new_obj)
    new_obj={}
  }
  // console.log(new_data)
}
generate_data(data)

在程式中使用從API取得的資料,執行console.log(data)就會跑出空陣列[],執行generate_data(data)則跑不出東西

截圖如下:
https://ithelp.ithome.com.tw/upload/images/20210127/20134762XuGifN407E.png
但在瀏覽器主控台兩者卻都可以正常執行。
https://ithelp.ithome.com.tw/upload/images/20210127/20134762G8Ix3RVr72.png

使用自己手動新增的資料,不管是在程式中,或是在主控台都能順利運作!

不知道是出了什麼問題@@?苦惱中...

優悠 iT邦新手 3 級 ‧ 2021-01-28 08:49:43 檢舉
ajax預設是異步,如:你寄出信件(使用AJAX),你就可以忙其他事了,但你要的東西(資料)還沒回來,以下需要此資料的事情都做白功。
若是同步,寄完信件,只能等它(資料)送回來,才能做其他事情,以下需要此資料的事情,才能跑出正常結果。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3

你不了解一件事。
ajax是一種callback+閉包的運行模式

在運行ajax,並不會等待運行完成。就會往下繼續跑。
所以你在當下其實還未拿到data值的。

你需要的是將要變動的值。放到ajax的success事件內去跑你的generate_data函式。

7
japhenchen
iT邦超人 1 級 ‧ 2021-01-28 08:11:02

你應該

$.ajax({
    .............
})
.done(function(data){
    newdata=null;
    generate_data(data);
    if(newdata!==null){
        // todo renderHTMLorDoSomething();
    }
})
.fail(function(data){
});

(但說真的,你改用$.get({url:...........})不是更簡單嗎?)

ajax({ })裡的success跟error就可以移掉了,我習慣放到done跟fail

8
froce
iT邦大師 1 級 ‧ 2021-01-28 09:02:49

不在意被堵塞或是使用者UX的話,可以加個async:false選項,讓ajax變成同步程式。

$.ajax({
    ..........
    async: false
})

但這不是推薦的方法喔,你遲早要搞懂 js異步程式。

0
EN
iT邦好手 1 級 ‧ 2021-01-28 14:45:17

如果要寫好程式,必須了解你所使用的語言的特性以及特例,關於 JS 如何做到異步操作,可以參考該影片

我要發表回答

立即登入回答