JavaScript - 手寫實現ajax 以及 ajax封裝

1.應用場景

主要用於與後端數據交互, 請求api獲取數據, 實現頁面的無刷新請求數據, 保證良好的用戶體驗.

2.學習/操作

服務端api

serve.php

<?php

 

$res = [

    'status' => 1, 

    'msg' => 'success', 

    'data' => [

        'id' => 1,

        'name' => 'williamning',

        'age' => 27

    ]

];

// sleep(2); //程序休眠2秒. 使得ajax請求超時

echo json_encode($res); //所以,最終的結果還是打印的方式輸出

前端

1.原生ajax //不是很完善, 主要用於學習

文件目錄結構

 

文件內容:

html

index.html

<!DOCTYPE html>

<html>

 

<head>

    <title>test ajax - with JavaScript</title>

    <script type="text/javascript" src="./request.js"></script>

</head>

 

<body>

    <div id='app'>

        hello world...

    </div>

    <script type="text/javascript">

        (function () {

            // console.log('start to run...');//just test to run

            const url = '../serve.php';

            const method = 'get';

            const async = true;

            const timeout = 1000;

            const data = { test: 1, aaa: 2 }; //對象

            ajax({

                url: url,

                method: method,

                async: async,

                timeout: timeout,

                data: data

            }).then(

                // res => console.log('請求成功: ' + res),

                res => successCallBack((res),

                    // err => console.log('請求失敗: ' + err)

                    err => failCallBack(err)

                ));

 

            function successCallBack(res) {

                const dom = document.getElementById('app');

                res = JSON.parse(res);  //api返回的json數據是字符串, 但是需要轉換爲JS對象,方可進行屬性讀寫值操作.

                dom.innerHTML = resJoin(res);

            }

 

            function resJoin(res) {

                let str = '';//需要初始換賦值爲空字符串,否則拼接時爲undefined

                for (let key in res) {

                    if (!res.hasOwnProperty(key)) {

                        continue;

                    };

                    if (typeof res[key] == 'object') {

                        str += '<span style="color:red">' + key + ':' + JSON.stringify(res[key]) + '</span><br/>';

                    } else {

                        str += '<span style="color:green">' + key + ':' + res[key] + '</span><br/>';

                    }

 

                }

                return str;

            }

 

            function failCallBack(err) {

                console.log('請求失敗: ' + err);

            }

        })();

    </script>

</body>

 

</html>

javascript

request.js

function ajax (options) {

    let url = options.url

    const method = options.method.toLocaleLowerCase() || 'get'

    const async = options.async != false // default is true

    const data = options.data

    const xhr = new XMLHttpRequest()

 

    if (options.timeout && options.timeout > 0) {

        xhr.timeout = options.timeout

    }

 

    return new Promise ( (resolve, reject) => {

        xhr.ontimeout = () => reject && reject('請求超時') //爲什麼前面沒有顯示出來 ? TBD

        // xhr.ontimeout = () => console.log('請求超時');//可以打印出來

        xhr.onreadystatechange = () => {

            if (xhr.readyState == 4) {

                if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {

                    resolve && resolve(xhr.responseText)

                } else {

                    reject && reject('請求失敗')

                }

            }

        }

        xhr.onerror = err => reject && reject(err)

 

        let paramArr = []

        let encodeData

        if (data instanceof Object) {

            for (let key in data) {

                // 參數拼接需要通過 encodeURIComponent 進行編碼

                paramArr.push( encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) )

            }

            encodeData = paramArr.join('&')

        }

 

        if (method === 'get') {

              // 檢測 url 中是否已存在 ? 及其位置

            const index = url.indexOf('?')

            if (index === -1) url += '?'

            else if (index !== url.length -1) url += '&'

              // 拼接 url

            url += encodeData

        }

 

        xhr.open(method, url, async)

        if (method === 'get') xhr.send(null)

        else {

            // post 方式需要設置請求頭

            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8')

            xhr.send(encodeData)

        }

    } )

}

請求截圖:

 

具體代碼解釋參考://講得很詳細

https://www.jianshu.com/p/d644c398be06  //前端面試題——手寫實現 ajax

 

jQuery ajax:

html

indexJq.html

<!DOCTYPE html>

<html>

 

<head>

    <title>test ajax - with jquery</title>

    <script src="../jquery/jquery-3.5.1.min.js"></script>

    <script src="../ajax/request_jq.js"></script>

</head>

 

<body>

    <div>

        hello world...

    </div>

    <script type="text/javascript">

        $(document).ready(function () {

            req_jq();

            console.log('rea_jq after');//會先執行 因爲是ajax請求是異步任務,這裏是同步任務

        });

    </script>

</body>

 

</html>

javascript

;

function req_jq(){

    const url = '../serve.php';

    const method = 'get';

    const async = true;

    const timeout = 1000;

    const dataType = 'json';

    const data = { test: 1, aaa: 2 }; //對象

    let ajaxTimeOut = $.ajax({

        url: url,

        type: method,

        async: async,

        dataType: dataType,

        timeout: timeout,

        data: data,

        success: function (data) {

            console.log("請求成功");

            console.log(data);

        },

        error: function (xhr, status, err) {

            console.log('請求失敗:', status, err);

        },

        complete: function (XMLHttpRequest, status) {

            if (status == 'timeout') {//status == 'timeout'意爲超時, status的可能取值:success,notmodified, nocontent, error, timeout, abort, parsererror 

                ajaxTimeOut.abort();//取消請求 在completezhiqian

                Modal.warning({//超時提示:網絡不穩定

                    title: '友情提示',

                    content: '網絡不穩定',

                });

            }

        }

    });

}

 

//告警對象

const Modal = {

    warning: function({title, content}){

        //  $("body").append(title + ': ' + content); //直接顯示頁面

        // alert(title + ': ' + content);//彈出警告框

        console.warn(title + ":", content); //控制檯輸出告警信息

    },

 

    error: function({title, content}){

        console.error(title, content); //控制檯輸出告警信息

    }

}

jquery 的代碼請自行下載.

 

截圖:

 

 

angularJS

TBD 

 

vue:

TBD

 

 

備註:

練習代碼見 GitHub

https://github.com/ningxiaofa/php-learning/tree/master/ajax_serve

 

 

後續補充

...

3.問題/補充

TBD

4.參考

https://www.jianshu.com/p/d644c398be06  //前端面試題——手寫實現 ajax

https://jquery.com/  //jqury官網

後續補充

...

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章