jyzwf / blog

在Issues里记录技术得点滴
17 stars 3 forks source link

JSONP 跨域 #50

Open jyzwf opened 6 years ago

jyzwf commented 6 years ago

前端代码

// index.js
(function (window) {
    let createTag = (tag, attrOpts) => { // 创建标签
        let Tag = document.createElement(tag)
        forEachValue(attrOpts, (key) => {
            Tag[key] = attrOpts[key]
        })
        return Tag
    }

    let forEachValue = function (obj, fn) {
        Object.keys(obj).forEach(key => fn(key))
    }

    // 注意,使用document.querySelector()获取 body元素 时,要传入 'body',而不是 document.body
    let appendChild = (parent, child) => {
        parent = document.querySelector(parent)
        parent.appendChild(child)

        return function () {
            parent.removeChild(child)
        }
    }

    let assert = (condition, msg) => { // 断言
        if (!condition) throw new Error(`${msg}`)
    }

    let jsonp = req => {
        let {
            url,
            data,
            callback
        } = req
        let script,
            removeChild,
            params = [],
            fnName = 'jsonpCb'

        data['callback'] = fnName

        assert(url, "url 不能为空")
        assert(callback, "url 不能为空")

        for (let key in data) {
            params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
        }

        url = url.indexOf('?') > 0 ? `${url}&` : `${url}?`

        url += params.join('&')

        script = createTag('script', {
            src: url,
            type: "text/javascript"
        })

        removeChild = appendChild('body', script)

        window[fnName] = res => {
            callback(res)
            removeChild()
            delete window[fnName]
        }

        script.onerror = (error) => {
            callback({
                error
            })
            removeChild()
            delete window[fnName]
        }

    }

    jsonp({
        url: 'http://localhost:8080/login',
        data: {
            name: 'echo666'
        },
        callback: function (res) {
            console.log(JSON.stringify(res));
        }
    })

})(this);

node 代码

var qs = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function (req, res) {
    var params = qs.parse(req.url.split('?')[1]);
    console.log(params)

    var fn = params.callback;

    // jsonp返回设置
    res.writeHead(200, {
        'Content-Type': 'text/javascript'
    });
    res.end(fn + '(' + JSON.stringify(params) + ')');

});

server.listen('8080');
console.log('Server is running at port 8080...');
happier2 commented 6 years ago

通过自己实现jsonp,完全掌握jsonp原理,👍