前端初学者:简易封装 AJAX

141 阅读2分钟

封装 AJAX

AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。对于前端初学者来说,封装一个 AJAX 函数是非常有必要的,能够大大减少代码量。

基本代码

/**
* ajax函数
 * @param {object} opt 
 */
function ajax(opt = {}) {
    //强制opt为对象
    opt = opt || {};
    //http连接的方式
    opt.method = opt.method || 'POST';
    //发送请求的url
    opt.url = opt.url || '';
    //是否为异步请求,true为异步的,false为同步的
    opt.async = opt.async || true;
    //发送的参数,类型为对象类型
    opt.data = opt.data || null;
    //预期服务器返回数据类型
    opt.dataType = opt.dataType || 'JSON';
    //ajax发送并接收成功调用的回调函数
    opt.success = opt.success || function() {};
    //ajax发送并接收失败调用的回调函数
    opt.error = opt.error || function() {};


    let xhr = null;
    if (window.XMLHttpRequest) {
        // IE7+, Firefox, Chrome, Opera, Safari 代码
        xhr = new XMLHttpRequest();
        //针对某些特定版本的mozilla浏览器的bug进行修正。
        if (xhr.overrideMimeType) {
            xhr.overrideMimeType('text/xml');
        }
    } else {
        // IE6, IE5 代码
        xhr = new ActiveXObject('Microsoft.XMLHTTP');

    }
    let params = [];

    // Object.keys(opt.data).forEach(key => { params.push(key + '=' + opt.data[key]) });
    for (let key in opt.data) params.push(key + '=' + opt.data[key]);

    let postData = params.join('&');
    //跨域请求
    if (opt.dataType === 'JSONP') {
        creatScript(opt.url, postData);
    } else {
        if (opt.method.toUpperCase() === 'POST') {
            xhr.open(opt.method, opt.url, opt.async);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
            xhr.send(postData);
            // xhr.setRequestHeader('Content-Type', 'application/json');
            // xhr.send(JSON.stringify(data));
        } else if (opt.method.toUpperCase() === 'GET') {
            if (postData.length > 0) {
                xhr.open(opt.method, opt.url + '?' + postData, opt.async);
            } else {
                xhr.open(opt.method, opt.url, opt.async);
            }
            xhr.send(null);
        }
        xhr.onreadystatechange = function() {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                // 信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)
                if (xhr.status >= 200 && xhr.status < 400) {
                    opt.success(xhr.response);
                } else if (xhr.status >= 400) {
                    opt.error(xhr.status);
                }
            };
        }
    }
}

当浏览器向服务端发送请求时,会时常碰到跨域问题。跨域是违反了浏览器的同源策略。同源策略,它是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指:域名,协议,端口相同。有一者不同都是违反同源策略。

我们可以使用 JSONP 的方式来解决跨域问题

JSONP 原理:
(1)前端事先定义了一个解析函数,是一个回调函数;
(2)但数据在服务端,客户端会把这个函数包装成参数传递给后端;
(3)服务端获取到该函数,把要返回的数据作为该函数参数并调用;
(4)前端接受到后,JS 引擎会执行该回调函数了,拿到后端传递的数据。

/**
 * 动态创建script标签
 * --------------------------------------------
 * 
 * 
 * @param {string} url 发送请求的url
 * @param {object} data 发送的参数
 */
function creatScript(url, data) {
    //应用搜索接口
    //JSONP get请求 
    //利用script标签的src属性没有同源策略限制这一特点,访问非同源数据
    let oScript = document.createElement('script');
    //回调函数名jsonp,远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调
    oScript.src = url + '?' + data + '&callback=jsonp';
    document.body.appendChild(oScript);
}