问题描述

在自定义Ajax请求时,想使用表单的方式发送post请求,发现后台获取不到数据,查看jquery源码发现,这是因为当Content-Type设为application/x-www-form-urlencoded时,所发送的请求数据格式是‘key1=value1&key2=value2’这样类似的字符串。所以要把发送的对象做一次处理。

解决方案

这是一个自定义的Ajax的例子。

/**
 * 将对象转化为url形式
 * @param obj
 * @returns {string}
 */
const convertToURL = function(obj) {
    let result = '';
    if(obj!== null && typeof obj === 'object') {
        for(var key in obj) {
            if(obj.hasOwnProperty(key)) {
                let tmp = `&${key}=${obj[key]}`;
                result += tmp;
            }
        }
        result = result.substring(1);
    }
    return result;
}
/**
 *  ajax方法
 * @param options = {
 *  url:    请求url
 *  type:   请求类型
 *  data:   请求数据
 * }
 * @returns {Promise}
 */
const myAjax = (options) => {
    return new Promise((resolve, reject)=> {
        const defaultOption = {
            url: false,
            type: 'GET',
            data: null
        };
        const config = Object.assign(defaultOption, options);
        const url = config.url;
        const type = config.type;
        if (!url) throw new Error('must defined url!');
        const xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
        xhr.open(type, url);
        xhr.timeout = 2000;
        xhr.ontimeout = function() {
            alert('您的网络有点慢,请检查您的网络是否正常!');
        }
        xhr.onreadystatechange = () => {
            const status = xhr.status;
            if(xhr.readyState == 4) {
                if(status>= 200 && status < 300 || status == 304){
                    resolve(window.JSON.parse(xhr.responseText));
                }else {
                    reject(status + ': ' + xhr.responseText);
                }
            }
        };
        // post
        if(type.toLowerCase() === 'post'){
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
            // xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
        }
        xhr.send(convertToURL(config.data));
        // xhr.send(JSON.stringify(config.data));
    });
};

Content-Type设为application/json注意事项

当设置为请求头的Content-Type设为application/json时,不能直接发送json对象,需要把json对象序列化才行。

xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send(JSON.stringify(config.data));

更多推荐

完全解决方案Content-Type设为application/x-www-form-urlencoded服务器端拿不到数据问题