javascript AJAX
AJAX
(Asynchronous JavaScript and XML)
非同步的JavaScript and XML
AJAX有以下的特性:
- 使用 JavaScript 為主要程式語言
- 使用 DocumentObjectModel 的方式編修HTML
- 使用 XML 做為資料交換的格式
- 使用 XHTML 與 CSS 以呈現資料
- 使用 XMLHttpRequest 物件來傳輸與接收資料
(Ref.)
目錄:
同步與非同步
同步: 打電話。需要等對方回應才能進行下一個步驟
非同步:傳訊息。不需要等對方回應,可以先去做其他的事情
同步案例:乒乓球
1.打乒乓球必須一來一回
function ping() {
console.log('ping!');
}
function pong() {
console.log('pong!');
}
function play() {
console.log('Go!');
ping();
pong();
console.log('Game Set!');
}
play();
console
"Go!"
"ping!"
"pong!"
"Game Set!" //按照順序
2.加入延遲時間的情況,其結果並沒有按照順序
function ping() {
console.log('ping!');
setTimeout(() => {
console.log('殺球!!!');
}, 3000)
//3000 mini secs = 3 secs
}
function pong() {
console.log('pong!');
}
function play() {
console.log('Go!');
ping();
pong();
console.log('Game Set!');
}
play();
console
"Go!"
"ping!"
"pong!"
"Game Set!"
"殺球!!!" // 殺球在game set 之後出現
AJAX優點
- 非同步:在不更新整個頁面的情況去修改部分的資料
- 常見用途:API
1. 非同步語法: promise(resolve, reject)
promise()
有兩個參數: 成功resolve
, 失敗reject
1.resolve
: 成功才做下一步.then()
,失敗則不做
let killer = new Promise((resolve, reject) => {
resolve('十萬福特');
});
killer.then( skill => { //上一步成功,才會接到這一步
console.log(skill);
})
console
"十萬福特"
2.reject
: 失敗時.then()
沒反應
let killer = new Promise((resolve, reject) => {
reject('十萬福特');
});
killer.then( skill => { //上一步成功,才會接到這一步
console.log(skill);
})
console: 沒有印出資料
(什麼都沒有)
3.失敗時,丟參數進去.catch(error => )
let killer = new Promise((resolve, reject) => {
reject('十萬福特');
});
killer.then( skill => { //上一步成功,才會接到這一步
console.log(skill);
}).catch( error => {
console.log('error = ' + error)} )
console
"error = 十萬福特"
setTimeout()
,用途:等到事件完成之後再呈現資料
4.加入延遲時間的情況
let killer = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('十萬福特');
}, 3000)
});
killer.then( skill => { //上一步成功,才會接到這一步
console.log(skill);
}).catch(error => {
console.log('error = ' + error)
})
console: 三秒之後印出十萬伏特
"十萬福特"
練習: 釋放大絕招遊戲
三秒內點五次按鈕,放出大絕招 元氣玉 完成品連結 https://codepen.io/tingtinghsu/full/qwbrMr
Step 1. jQuery起手式
$(document).ready(() => {
});
Step 2. 抓hitbutton
$(document).ready(() => {
$('#hitButton').click( evt => {
})
});
Step 3. 點擊計數
let chi = 0;
$(document).ready(() => {
$('#hitButton').click( evt => {
evt.preventDefault();
chi += 1;
$('#hitButton').text(`集氣 (${chi} 次) `);
})
});
Step 4. 設定 promise
函數: 成功resolve, 失敗reject
let 大絕招 = new Promise((resolve, reject) => {
setTimeout(() => {
if( chi >= 5 ) {
resolve('元氣玉');
} else {
reject('元氣玉');
}
}, 3000)
})
Step5. 成功和失敗時所呈現的html
大絕招.then(招式 => {
$('#result').html(`使用絕招:${招式}`)
}).catch(err => {
$('#result').html(`${err}無法使用!`)
})
Step6. 整理成一行
大絕招
.then(招式 => $('#result').html(`使用絕招:${招式}`))
.catch(err => $('#result').html(`${err}無法使用!`))
小結
let chi = 0;
$(document).ready(() => {
$('#hitButton').click( evt => {
evt.preventDefault();
chi += 1;
$('#hitButton').text(`集氣 (${chi} 次) `);
})
});
let 大絕招 = new Promise((resolve, reject) => {
setTimeout(() => {
if( chi >= 5 ) {
resolve('元氣玉');
} else {
reject('元氣玉');
}
}, 3000)
});
大絕招.then(招式 => {
$('#result').html(`使用絕招:${招式}`)
}).catch(err => {
$('#result').html(`${err}無法使用!`)
})
2. 什麼是API
Application Programming Interface
應用程式介面
提供開發人員一些預先定義好的函式庫,可以快速使用其功能而不必了解實際運作。
常見的Web API回應格式
有 JSON / XML / CSV 這三種
JSON
JavaScript Object Notation
JavaScript的物件表示法
JSON資料格式的表示
https://jsoneditoronline.org/
物件(object)用大括號 { } 陣列(array)用中括號 [ ]
範例:
{
"name": "Ting",
"lastname": "Ting",
"report": [
{
"subject": "Math",
"score": 80
},
{
"subject": "English",
"score": 90
}
]
}
XML
Extensible-Markup Language
可延伸標記語言
意思是:有含意的標籤取名
<news>
<to>日本</to>
<from>台灣</from>
<heading>鈴木一朗要退休了!</heading>
<body>不.....................</body>
</news>
CSV
Comma-Separated Values
逗號分隔值
"1997","Ford","E350"
練習: 製作API抓取網路資料
農產品價格 完成品:https://codepen.io/tingtinghsu/full/QPyerz
Step 1. jQuery起手式
//希望DOM元素載完再做其他的事情
$().ready(() => {
});
Step 2. fetch()
抓網路資料,使用 fetch()
抓資料網址
http://data.coa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx
回傳一個Promise(). then()可以接著處理抓回來的資料
//DOM元素載完後再做其他的事情
$().ready(() => {
fetch('http://data.coa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx').then( response => { console.log(response)})
});
console 出現錯誤訊息:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at http://data.coa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
出現了關於CORS
的警告訊息
CORS的含義
Cross-Origin Resource Sharing
跨網域資料分享
若是抓取的網站沒有開CORS,可以
- 使用CORS Proxy(可能不太穩定)
- 用後端程式抓
改成另外的網址
//DOM元素載完後再做其他的事情
$().ready(() => {
fetch('https://ubin.io/data/vegetables?item=香蕉').then( response => { console.log(response)})
});
console
Response { type: "cors", url: "https://ubin.io/data/vegetables?item=%E9%A6%99%E8%95%89", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, body: ReadableStream, bodyUsed: false }
Step 3. 把抓取菜價的功能提出成為function getVegetablePrice()
可傳不同的蔬菜參數進去
$().ready(() => {
getVegetable('香蕉');
});
function getVegetable(item) {
fetch(`https://ubin.io/data/vegetables?item=${item}`).then( response => {
console.log(response)
})
}
console
Response { type: "cors", url: "https://ubin.io/data/vegetables?item=%E9%A6%99%E8%95%89", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, body: ReadableStream, bodyUsed: false }
Step 4. 解析轉成json格式,再回傳一個promise
function getVegetable(item) {
fetch(`https://ubin.io/data/vegetables?item=${item}`)
.then( response => {
// 解析轉成json格式
return response.json()
// 再回傳一個promise
})
.then(data => {console.log(data)})
}
console
item: "香蕉"
prices: (9) […]
0: Object { market: "台北二", price: 23.8 }
1: Object { market: "台北一", price: 22.4 }
2: Object { market: "板橋區", price: 24.6 }
3: Object { market: "三重區", price: 24.7 }
4: Object { market: "宜蘭市", price: 22 }
5: Object { market: "台中市", price: 21.2 }
6: Object { market: "豐原區", price: 19.38 }
7: Object { market: "高雄市", price: 25 }
8: Object { market: "鳳山區", price: 23 }
length: 9
把資料做成圖表的js函式庫: Chart.js
1.installation
Chart.js:https://cdnjs.com/libraries/Chart.js
將js檔案另存新檔,放入資料夾。
2.usage
https://www.chartjs.org/docs/latest/getting-started/usage.html
html
<head>
<script src="scripts/Chart.min.js"></script>
</head>
<body>
<canvas id="myChart" width="400" height="400"></canvas>
<script src="scripts/script.js"></script>
</body>
javascript
function getVegetable(item) {
fetch(`https://ubin.io/data/vegetables?item=${item}`)
.then( response => {
// 解析轉成json格式
return response.json()
// 再回傳一個promise
})
.then(data => { renderChart(data);}) //畫圖
}
Step 5. renderchart抓取蔬果資料(變數: market/price)
ES6的 .map()
:
針對某個陣列的每個元素做某件事情,再重新搜集成一個陣列
function renderChart(data) {
let markets = data["prices"].map(p => {
return p.market
//等於 return price["market"]
})
//測試 console.log(markets);
let prices = data["prices"].map(p => {
return p["price"]
})
// 測試 console.log(prices);
整理更簡潔的程式碼
let markets = data["prices"].map(p => p.market)
let prices = data["prices"].map(p => p.price)
最後,把抓好的資料填進去圖表!
let title = `${data.item}價格`;
var ctx = $('#myChart');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: markets, //各地市場
datasets: [{
label: title, // 標題
data: prices, // 價格
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(155, 199, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
相關連結
HackMD筆記
CodePen練習一
CodePen練習二
網頁版-釋放放大絕招遊戲
網頁版-API抓資料
JSON Viewer(Chrome 外掛)
Chart.js
政府資料交換平台
農產品交易行情(官方版)
農產品交易行情(特製版)