2018年5月16日 星期三

axios、fetch (React 16 六)

因為 react 沒有 ajax 功能,所以使用第三方的 axios,或者用 javascript 內鍵的 fetch
axios,使用原始的 XmlHttpRequest (XHR)
fetch,ES6 加入的功能,所以舊的瀏覽器沒有這功能


※servlet

@WebServlet("*.do")
public class XxxAction extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String acc = request.getParameter("acc");
        String pwd = request.getParameter("pwd");
        response.getWriter().append(acc + "-" + pwd);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("POST");
        this.doGet(request, response);
    }
}

※寫一支測試用的 servlet



※axios

class Test extends React.Component {
    handleAxios = _ => {
        // GET
        axios.get("abc.do?acc=aaa&pwd=pass")
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    
    
        // POST     
        const params = new URLSearchParams();
        params.append('acc', 'aaa');
        params.append('pwd', 'pass');
    
        axios.post('abc.do', params) // 也可學get在後面加
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    
    
        // AXIOS API - GET
        axios({
            method:'get',
            url:'abc.do?acc=aaa&pwd=pass',
        })
        .then(res => {
            console.log(res)
        });
    
    
        // AXIOS API - POST
        const params = new URLSearchParams();
        params.append('acc', 'aaa');
        params.append('pwd', 'pass');
    
        axios({
            method: 'post',
            url: 'abc.do', // 也可學get在後面加
            data: params
        }).then(res => {
            console.log(res)
        });
    }
    
    render() {
        return (
            <button onClick={this.handleAxios}>按我</button>
        )
    }
}
    
ReactDOM.render(<Test />, document.querySelector("#xxx"));

※post 要使用 URLSearchParams 或第三方的 query-string,可參考npm官網,但我在 npm 環境不用 URLSearchParams 也可以成功,如下:

import React, { Component } from 'react';
import axios from 'axios';
    
class Test extends Component {
    handleAxios = _ => {
        axios.post('http://localhost:8888/TestServlet/abc.do?acc=aaa&pwd=pass', {
            acc:'aaa',
            pwd:'pass'
        })
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    }
    
    render() {
        return (
            <button onClick={this.handleAxios}>按我</button>
        )
    }
}

※如果出現「 No 'Access-Control-Allow-Origin' header is present on the requested resource.」表示不能跨域,可以用瀏覽器的跨域功能 (chrome 在這裡),或者 nginx 的跨域功能如下:


server {
    listen 8888;
    server_name localhost;
    charset UTF-8;
    
    location / {
        proxy_pass http://localhost:10080;
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    
        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
        }
    
        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
        }
    }
}

※收到 localhost:8888 請求後,會導到 localhost:10080,並使用跨域功能

※同源策略:如 http://localhost
1.http
2.localhost
3.port,沒寫就是 80
以上三個一樣才算是同源,如果不同源就不允許跨域
還可參考高手寫的

※還可以使用 query-string,尤於沒找到 browser 的下載點,所以使用 node.js
yarn add query-string

使用時只要  import queryString from 'query-string';
然後 queryString.stringify({acc:'bbb', pwd:'ccc'} 放在 post 第二個參數就搞定了,但 post 不能在第一個參數的 ? 後面加參數,否則會以第一個參數為主


※fetch

// GET
fetch('abc.do?acc=aaa&pwd=pass', {
    method: 'GET'
}).then(res => { 
    console.log('res1=' + res);
})
.catch(err => console.error(err))
    
    
// POST
const params = new URLSearchParams();
params.append('acc', 'aaa');
params.append('pwd', 'pass');
    
fetch('abc.do', { // 也可學get在後面加
    method: 'POST',
    body: params
})
.then(res => res.json)
.then(data => {debugger;
    console.log(data.message)
})
.catch(err => console.error(err))

※參考mozilla 官網

沒有留言:

張貼留言