web端get和post请求支持跨域请求

最近在使用React框架,项目中用用到网络请求,请求存在跨域请求,最开始用的是jquery框架中的ajax的跨域请求(jsonp),感觉一个请求用jquery框架有点臃肿,然后就想着自己去写一个网络请求的类,在此记录一下。
XMLHttpRequest进行get和post请求:
//创建发送请求
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); //兼容ie
    xhr.open(options.method, options.url, options.async);
    if (options.method.toLowerCase() == 'post') {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(options.data);
    } else {
        xhr.send(null);
    }
    //异步请求
    if (options.async == true) {
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                callcall();
            }
        }
    }
    // xhr.abort(); // 取消异步请求
    //同步请求
    if (options.async == false) {
        callcall();
    }
    //返回状态判断
    function callcall() {
        if (xhr.status == 200) {
            var data = xhr.responseText.responseData;
            if (data.rtnCode == '000000') {
                options.success(data);
            }else {
                options.error(data);
            }
        } else {
            options.error('error:' + xhr.status + xhr.statusText);
        }
    }

其中options是上传需要的参数。
主要是记录一下跨域请求,跨域请求有两种方式:

  • 通过对外域服务器的响应都添加Access-Control-Allow-Origin信息头,来告诉浏览器允许使用外域数据。
  • 用Script来模拟请求,返回数据(jsonp)完整代码如下(用的es6中的写法,jsx语言):
* options{
 * async:true(异步)或 false(同步)
 * method:请求的类型;GET 或 POST
 * url:文件在服务器上的位置
 * dataType:请求类型 支持jsonp
 * jsonp:jsonp方式请求成功后返回的包含字段
 * timeout:请求超时时间
 * data:请求参数
 * error:请求返回错误
 * success:请求返回成功
 * }
 * */

const urlHttp = "";

const ajax = (options) => {
    //默认参数
    options.url = options.url || '';
    options.async = options.async || true;
    options.method = options.method || 'get';
    options.data = options.data || '';
    options.timeout = options.timeout || 3000;
    options.url = urlHttp + options.url;//拼接服务器地址
    //如果是jsonp请求(默认改成get请求)
    options.success = options.success || '';
    if (options.dataType === "jsonp") {
        options.jsonp = options.jsonp || "jsoncallback";
        options.method = 'get';
    }
    //get请求-拼接url
    if (options.method.toLowerCase() == 'get') {
        if (typeof options.data == 'object') {
            var datas = "";
            for (var key in options.data) {
                datas += key + "=" + options.data[key] + "&";
            }
        }
        if (datas) {
            options.url += (options.url.indexOf('?') == -1? '?' : '') + datas;
        }
        if (options.dataType === "jsonp") {
            jsonpHttp(options);//跨域请求
            return
        }
    }
    //post请求-转换字符串
    if (options.method.toLowerCase() == 'post') {
        if (typeof options.data == 'object') {
            var arrs = [];
            for (var k in options.data) {
                arrs.push(k + '=' + options.data[k]);
            }
            options.data = arrs.join('&');
        }
    }
    //创建发送请求
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); //兼容ie
    xhr.open(options.method, options.url, options.async);
    if (options.method.toLowerCase() == 'post') {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(options.data);
    } else {
        xhr.send(null);
    }
    //异步请求
    if (options.async == true) {
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                callcall();
            }
        }
    }
    // xhr.abort(); // 取消异步请求
    //同步请求
    if (options.async == false) {
        callcall();
    }
    //返回状态判断
    function callcall() {
        if (xhr.status == 200) {
            options.success(xhr.responseText);
        } else {
            options.error('error:' + xhr.status + xhr.statusText);
        }
    }
};

const jsonpHttp = (options) => {
    //如果是跨域请求
    var timeoutId = undefined;
    var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
    var scriptId = '_' + callbackFunction;
    window[callbackFunction] = function (response) {
        options.success(response);
        if (timeoutId) {
            clearTimeout(timeoutId)
        }
        ;
        removeScript(scriptId);
        clearFunction(callbackFunction);
    };
    var jsonpScript = document.createElement('script');
    jsonpScript.setAttribute('src', '' + options.url + "&" + options.jsonp + '=' + callbackFunction);
    jsonpScript.id = scriptId;
    document.getElementsByTagName('head')[0].appendChild(jsonpScript);

    timeoutId = setTimeout(function () {
        console.log('JSONP request to ' + options.url + ' timed out');
        clearFunction(callbackFunction);
        removeScript(scriptId);
    }, options.timeout);

    //出现 404/500
    jsonpScript.onerror = function () {
        console.log('JSONP request to ' + options.url + ' failed');
        clearFunction(callbackFunction);
        removeScript(scriptId);
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
    };

    return;
};

//jsonp 请求返回的包裹
const generateCallbackFunction = () => {
    return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
};
//jsonp请求成功后清除返回的方法
const clearFunction = (functionName) => {
    // IE8 throws an exception when you try to delete a property on window
    // http://stackoverflow.com/a/1824228/751089
    try {
        delete window[functionName];
    } catch (e) {
        window[functionName] = undefined;
    }
};
//jsonp请求相当于是用Script的src请求,请求成功后就清除请求是创建的Script
const removeScript = (scriptId) => {
    var script = document.getElementById(scriptId);
    if (script) {
        document.getElementsByTagName('head')[0].removeChild(script);
    }
};

export default ajax;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值