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官网

后续补充

...

猜你喜欢

转载自blog.csdn.net/william_n/article/details/106721816