iT邦幫忙

2022 iThome 鐵人賽

0
Modern Web

從新開始學習p5.js畫出一片天系列 第 32

D32_網路讀取資料的操作(JS AJAX, CORS)

  • 分享至 

  • xImage
  •  

網路讀取資料的操作(JS AJAX, CORS)

今天來整理一下使用 HTTP GET,POST,DO 的資料請求通訊方式讀取資料的操作。

一般要從網路上讀取資料,在p5.js中,提供了3種常見的方法
httpGet() 用於以URL的連結讀取資料,不用上傳相關參數資料。
httpPost() 用於以URL的連結讀取資料,不用上傳相關參數資料。
httpDo() 比較是通用型的讀取資料協定格式

httpGet(path, [datatype], [data], [callback], [errorCallback])
httpGet(path, data, [callback], [errorCallback])
httpGet(path, callback, [errorCallback])

httpPost(path, [datatype], [data], [callback], [errorCallback])
httpPost(path, data, [callback], [errorCallback])
httpPost(path, callback, [errorCallback])

httpDo(path, [method], [datatype], [data], [callback], [errorCallback])
httpDo(path, options, [callback], [errorCallback])

path: URL
datatype: "json", "jsonp", "binary", "arrayBuffer", "xml", or "text"
data: Object|Boolean -> {id:"123", name:"jason"}, false/true

不過經過測試發現p5.js提供的 httpGet(),httpPost(),httpDo()這3種方法,只有支援GET的method,
POST的方法無法將參數傳送出去,因此只能使用 在URL中串參數的方法,

結果就是只能使用 httpGet(path, [datatype], [callback])
其中URL加上參數的格式 例如: getData.php?id=123&name=jason

let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
function setup() {
	const xget = httpGet(url, 'json', false, (res) => {
	    console.log(res);   //-- 回傳結果在 PromiseResult 中
        console.log(xget);  //-- 建立 Promise 物件
	});
}

JSON資料來源為 政府資料開放平台「臺北市停車場資訊V2」,網址為 https://data.gov.tw/dataset/128435

讀取到的資料如下
httpGet

有時候在讀取資料時會發生CORS的問題,
這時就要透過PHP來當作中介讀取資料,再回傳給前端
JS

let url = "getData_GET.php?urlx=https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json";
const xget = httpGet(url, 'json', false, (res) => {
    console.log(res);
    console.log(xget);
});

PHP (getData_GET.php)

<?php 
  $urlx = $_GET["urlx"];
  $opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/x-www-form-urlencoded',
        //'content' => $postdata
    )
  );

  $context  = stream_context_create($opts);
  $result = file_get_contents($urlx, false, $context);
  echo $result;
?>

接著來看一下Native JS的方法,使用的是 XMLHttpRequest()

let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
const xhttp = new XMLHttpRequest();  //-- 建立 XMLHttpRequest物件
xhttp.onload = function() {
    console.log(this); 
    console.log(this.responseText);
    console.log(this.getResponseHeader("Last-Modified"));  //-- 讀取head表頭參數 Last-Modified 的內容
	console.log(this.getAllResponseHeaders());  //-- 讀取全部head表頭參數的內容
}
xhttp.open("GET", url, true);
xhttp.send();

查看一下XMLHttpRequest物件的屬性及方法
XMLHttpRequest物件

XMLHttpRequest GET方法

JS

let url = "getData_GET.php?id=2&name=Jason";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
    console.log(this.responseText);
    console.log(this.getAllResponseHeaders());
}
xhttp.open("GET", url, true);
xhttp.send();

PHP (getData_GET.php)

<?php 
  echo $_GET["id"].", ".$_GET["name"];
?>

XMLHttpRequest POST方法

JS

let url = "getData_POST.php";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
    console.log(this.responseText);
    console.log(this.getAllResponseHeaders());
}
xhttp.open("POST", url);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("id=2&name=Jason");

PHP (getData_POST.php)

<?php 
  echo $_POST["id"].", ".$_POST["name"];
?>

如果回傳內容是JSON格式,要另外用JSON物件轉換

let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
    console.log(this);
    const json_obj = JSON.parse(this.responseText);
    console.log(json_obj);
    console.log(this.getAllResponseHeaders());
}
xhttp.open("GET", url, true);
xhttp.send();

有時候在讀取資料時會發生CORS的問題,
這時就要透過PHP來當作中介讀取資料,再回傳給前端
JS

const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
    const json_obj = JSON.parse(this.responseText);
    console.log(json_obj);
    console.log(this.getAllResponseHeaders());
}

xhttp.open("POST", "getData_POST.php");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("urlx=https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json");

PHP (getData_POST.php)

<?php 
  $urlx = $_POST["urlx"];
  $opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/x-www-form-urlencoded',
    )
  );
  $context  = stream_context_create($opts);
  $result = file_get_contents($urlx, false, $context);
  echo $result;
?>

php用到的指令

stream_context_create(?array $options = null, ?array $params = null): resource

file_get_contents(
    string $filename,
    bool $use_include_path = false,
    ?resource $context = null,
    int $offset = 0,
    ?int $length = null
): string|false

另外,在以POST傳送資料時,可以先用物件格式編輯參數內容,轉換成 url query parameters的格式

let postData = {
	id: 123,
    name: "Jason"
};
let pdata = Object.entries(postData).map( ([key, val]) => `${key}=${val}` ).join('&');
console.log(pdata);  //--  id=123&name=Jason

其中 Object.entries(postData) 是將object轉換成陣列

console.log(Object.entries(postData));

再利用 map(([key, val]) => ${key}=${val}) 組合 參數對陣列

console.log(Object.entries(postData).map(([key, val]) => `${key}=${val}`));

最後再用 join('&') 將參數對陣列串接成字串,並以'&'串接

console.log(Object.entries(postData).map(([key, val]) => `${key}=${val}`).join('&'));

參數對陣列

最後的程式碼

let postData = {
	urlx: "https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json",
};

function setup() {
	const xhttp = new XMLHttpRequest();
	xhttp.onload = function() {
		const json_obj = JSON.parse(this.responseText);
		console.log(json_obj);
		console.log(this.getAllResponseHeaders());
	}

	let pdata = Object.entries(postData).map(([key, val]) => `${key}=${val}`).join('&');

	xhttp.open("POST", "getData_POST.php");
	xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xhttp.send(pdata);
}

參考資料
httpGet()
https://p5js.org/reference/#/p5/httpGet
JavaScript Array join()
https://www.w3schools.com/jsref/jsref_join.asp
AJAX - The XMLHttpRequest Object
https://www.w3schools.com/js/js_ajax_http.asp
file_get_contents
https://www.php.net/manual/zh/function.file-get-contents.php
stream_context_create
https://www.php.net/manual/zh/function.stream-context-create.php


上一篇
D31_網頁中表格的介面操作
下一篇
D33_網路通訊資料傳送的操作(WebSocket, OSC, MQTT)
系列文
從新開始學習p5.js畫出一片天40
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言