JSONP

227 阅读1分钟

同源策略

现在所有支持JavaScript的浏览器都会使用同源策略。

所谓同源是指,域名,协议,端口相同。

解决这种同源策略的方法称之为跨域,跨域的方法有很多种,jsonp跨域是最经典的一种。

JSONP

JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

JSONP实现 -- CallBack

创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

简单实现

fe.html

        <script>
            function jsonP (option) {
                const { url, callback } = option
                return new Promise((resolve, reject) => {
                    let methodName = 'abc'
                    window[methodName] = function (data) {
                        resolve(data)
                        console.log('window')
                        // 删除
                        delete window[methodName]
                        document.body.removeChild(scriptNode)
                    }
                    // 生成script
                    let scriptNode = document.createElement('script')
                    scriptNode.src = `${url}?${callback}=${methodName}`
                    // http://localhost:3002/api/books?getBook=abc
                    console.log(`${url}?${callback}=${methodName}`)
                    document.body.appendChild(scriptNode)
                    // 失败
                    scriptNode.onerror = function () {
                        reject('error')
                    }
                })
            }
            // 跨域
            jsonP({
                url: 'http://localhost:3002/api/books',
                callback: 'getBook'
            }).then(res => {
                console.log('---------',res)
            })
        </script>

node.js

        const http = require('http')
        
        http.createServer((req, res) => {
            const url = require('url').parse(req.url)
            if (url.pathname === '/api/books') {
                // url.query getBook=abc
                console.log('url.query', url.query)
                const methodName = url.query && url.query.split('=')[1]
                // methodName abc
                console.log('methodName', methodName)
                let list = [{name: 'book1', price: 33}]
                // abc([{"name":"book1","price":33}])
                console.log(`${methodName}(${JSON.stringify(list)})`)
                res.end(`${methodName}(${JSON.stringify(list)})`)
            }
        }).listen(3002, () => {
            console.log('server is running http://localhost:3002')
        })