资讯专栏INFORMATION COLUMN

通俗易懂讲解跨域的前世今生

Michael_Lin / 3370人阅读

摘要:把数据包裹在一个客户端声明的本地的回调函数中,这样可以动态加载一个跨域服务器数据。在本地声明这个动态中的回调函数名称,并且定义该函数,然后通过参数传递到服务器。

为什么要跨域

我们都知道在浏览器地址栏输入地址的时候可以随便访问一个页面,但是如果你在ajax请求中发出一个xhr请求那么因为浏览器安全策略只有同源的服务器才能处理。这就是同源策略 要求协议/域名/端口三者完全一致才能访问

例如以下的代码例子,我们需要获取服务器上README.md里面的数据

{
  status:"sucess",
  data:{
    city:["南京","北京"]
  }
}

本地js代码如下

  

如果地址栏是下面这样

那么我们是可以访问到这个数据文件的

如果我在另外一个不同源域名下执行同样的代码例如下面这个地址

那么就会出现下面的错误

这个错误的意思说白了就是服务器禁止不同源的页面进行ajax请求数据。

非要获取这个数据我们应该怎么做

我们注意到有的网站会提供cdn服务我们可以从不同的服务器添加下面的代码

这就为我们跨域获取数据提供了可能

node服务器端代码如下
var path = require("path")
var express = require("express")
const app = express()
app.use(express.static(path.join(__dirname, "jsonp")))
console.log("> Starting dev server...")
app.get("/detail", (req, res) => {
    let cb = req.query.cb ? req.query.cb : null
        // console.log("succuess")
    let readStream = fs.createReadStream(`README.md`)
    let data = ""
    readStream.on("data", chunk => {
        data += chunk
    })
    readStream.on("end", () => {
        // console.log(data)
        res.send(`${cb}(${data})`)
    })
})
var server = app.listen(8888)
console.log("server is running at port 8888")

1.基本原理我们可以动态生成script标签,把请求的url添加到script标签的src属性上。把数据包裹在一个客户端声明的本地的回调函数中,这样可以动态加载一个跨域服务器数据。

  function jsonp(obj) {
            let scriptDOM = document.createElement("script")
            scriptDOM.setAttribute("src", `${obj.url}?cb=${obj.cb}`)
            window["callback"] = obj.success
            document.querySelector("body").appendChild(scriptDOM)
            scriptDOM.onload = function() {
                window["callback"] = null
                this.parentNode.removeChild(this)

            }
            scriptDOM.onerror = e => {
                console.log("jsonp error!", e)
            }




        }
        jsonp({
            url: "http://localhost:8888/detail",
            cb: "callback",
            success: data => {
                if (data) {
                    console.log("jsonp data", data)
                }
            }
        })

2.在本地声明这个动态script中的回调函数名称,并且定义该函数,然后通过url参数传递到服务器。服务器把数据包裹成这个函数的参数传递回来,跨域就实现了。

为什么要这么做?以前我也很困惑。你获取到的数据有可能是个json也有可能是个纯文本,而script标签内的内容只能是合法的js语句,如果你没有用回调函数包裹,直接从服务器传递回来原生数据。有可能是一段恶意代码,或者是非法的js字符,那么浏览器就会报错或者产生不可预料的显示结果。并且你事先不知道浏览器传递过来的代码跟你写的有没有冲突,是不是完全耦合。只有在本地定义一个函数传递到服务器,这样服务器用该函数包裹代码后传递回来才能跟我们的本地js代码紧密配合。这样服务器传递回来执行的代码就是我们自己定义的函数(数据存在函数的参数里),可以很好跟我们自己的代码配合。这样颇有Vue Angular子组件向父组件传递数据的思想

这样不同域名下的数据我们拿到了结果如下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82767.html

相关文章

  • ES6-前世今生(0)

    摘要:更新了个版本,最新正式版是语言的下一代标准,早已在年月正式发布。基本不支持移动端浏览器对的支持情况版起便可以支持的新特性。比较通用的工具方案有,,,等。 1、ECMAScript是什么? 和 JavaScript 有着怎样的关系? 1996 年 11 月,Netscape 创造了javascript并将其提交给了标准化组织 ECMA,次年,ECMA 发布 262 号标准文件(ECMA-...

    LeviDing 评论0 收藏0
  • python协程的前世今生

    摘要:协程的历史说来话长,要从生成器开始讲起。我们可以使用把数据发送给协程函数。可以看到,在第次接收完数据之后,会产生结束的异常,因为程序流程结束了,这是正常现象。在这个阶段,协程本质上还是由生成器构成的。所以,协程的介绍到这里就结束啦。 在上一篇对python并发编程的理解 中,我简单提到了协程的概念,有一个错误需要指出的是,asyncio不全是对协程的实现,只是用到了协程。 协程的历史说...

    stackfing 评论0 收藏0
  • 有价值的前端技术点

    摘要:借着产品层面的功能和视觉升级,我们用对它进行了一次技术重构。前端优化是一个让人技术提升的,希望你也能从这里学到一些东西。年最流行的前端链接我们每周会给多名前端开发者发送新闻邮件。 面试 -- 网络 HTTP 现在面试门槛越来越高,很多开发者对于网络知识这块了解的不是很多,遇到这些面试题会手足无措。本篇文章知识主要集中在 HTTP 这块。文中知识来自 《图解 HTTP》与维基百科,若有错...

    microelec 评论0 收藏0
  • kube-dns的前世今生

    摘要:通过监视资源的变化,并根据的信息生成记录写入到中。是唯一保留的容器,依然提供健康检查。操作会获取最新的全量资源与本地状态进行比较来产生通知,可以避免网络原因导致的丢失通知的情况。最后一个参数用来设置处理事件的回调。 上一期我们以1.2版本为背景,介绍了K8S的服务发现和kube-dns插件的相关内容。有了上一期内容作为基础,这期了解最新版本的kube-dns就会容易很多。 本文主要对比...

    Lin_R 评论0 收藏0
  • Web技术的前世今生(二)

    摘要:前言我是,如果你还不认识我,不妨先看看技术的前世今生一平静的生活已经有一段日子了。传送门技术的前世今生一技术的前世今生三 前言:我是JavaScript,如果你还不认识我,不妨先看看《Web技术的前世今生(一)》 平静的生活已经有一段日子了。 这一天,HTML大哥面露不悦地走过来问我: Js,你是打算和我们分家吗? 大哥,您这说的哪里话,我什么地方做的不对么?我一脸茫然地回答道。 哼,...

    Stardustsky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<