高级课程jsonp2.0

什么是数据库?//只要一个东西可以永久存放数据就是数据库,不管是硬盘啊,光盘啊~~~

MYSQL 即是软件,也是一种数据库,这个软件的功能,就是数据库.MYSQL,是最流行的数据库,my是作者女儿的名字缩写,SQL是一种结构化查询语言~

  • 文件系统就是一种数据库,文件可以增删改查
  • 数据库,能长久存储数据的地方就是数据库,不管是光盘,硬盘~都是
  • 提到了之前的http服务器知识,其中提到了请求路径和文件名只是恰巧一样而已,两者并没有关联关系
  • 在服务器上做一个简单的加法运算
button.addEventListener('click',(e)=>{
      let n = amount.innerText
      let number = parseInt(n,10) // n-0也行,因为JavaScript的运算符的转换机制
      let newNumber = number - 1
      amount.innerText = newNumber 
//这是页面按钮,被点击,100余额就被减少,可是这只是页面上的操作,当页面刷新,数字还是变回100,那么这些代码就失去意义了~/所以需要数据库的存在,把数据存在数据库里面,变化能够记住~
})
  • 给页面上的余额一个占位符,因为有很多个用户,不可能每个用户都只有100余额吧

  • 前端后端代码有关联但不是一起的,所以前端后端出现同名变量很正常,后台代码

  • 逻辑: JavaScript页面代码只是操作页面的动作,后台没有数据记忆,所以需要用能发post请求的标签(用到标签当然是html的范畴了)去更改后台数据库的数据,/为什么是post? 因为是修改东西,并不是请求东西,也就是说,当页面付款按钮被点击,后台数据库里面的余额要知道扣多少钱,也就是说修改后台数据库里的数据所以是post请求

  if(path === '/pay' && method.toUpperCase()=== 'POST'){
    var amount = fs.readFlieSync
    var newAmount  = amount - 1
    fs.writeFileSync('./db',newAmount)
    response.write('success')
    response.end() 
  }else{....

也就是说:浏览器向服务器请求网页文件,服务器响应,给浏览器对应文件,浏览器渲染整个页面,当用户点击页面上被form标签包裹的付款按钮,浏览器就发送post请求告诉服务器,数字更改了;服务器获取到这个信息,然后去数据库修改数据并且保存,又响应浏览器,实现前端后端数据一致
//老师演示的代码,后端是用了代码自动减一来实现,实际上并没有监听到余额

  • 2005年之前都是这样付款的,付款之后都要刷新一下当前页面,才知道付款是否成功,体验是比较差的~
  • 于是程序员们,想尽办法提升用户体验,首先想到的是用iframe+form表单标签,因为form标签会刷新当前页面,不管成功失败
  • 第二种办法,前端人员发现,用JavaScript代码,新建一个img标签,就会自动发送一个get请求,JavaScript里面的image.onload方法可以检测到浏览器图片下载成功,image.onerror方法可以知道浏览器图片下载失败,利用这个特性,实现页面自动刷新,不用让用户自己动手,提升体验//这个方法缺陷是,只有get没有post//
let image = document.createElement('img')
image.src = '/pay'
iamge.onload = function(){alert'打钱成功'  amount.innerText -1 }
image.onerror = function (){
alert('打钱失败')}
  • 所以第三种办法想出来了,用script标签,不过这个script标签必须要放在body里面才会自动发送请求这个思路是后台直接修改数据'值'(也就是后台帮页面修改数据值),不用浏览器刷新了,彻底提高体验效果
  • 说白了,就是让服务器返回一个 'conten-type'为JavaScript的字符串,让浏览器执行这些字串,效果一样,就不用像以前那样刷新页面了~完美
///这是前端的
button.addElementListener('click',(e)=>{
  let script = document.createElement('script')
  script.src ='/pay'
  document.body.appendChild(script)//如果不包裹在body里面这个生成的script是没有自动发送的效果的
  script.onload = function(e){
        e.currentTarget.remove//这只是移除这个script标签,代码变量都在内存里面,没有删除,所以效果出来了,标签也删除了,完美
      }
})
      script.onerror = function(xxx){
          alert('fail')
          e.currentTarget.remove()  //因为服务器返回的是可执行的JavaScript代码字符串,所以script会执行,在network下面会多出多个无用字符,这是为了清除这些无用字符的,为了美观
      }
///为什么这些字串页面会执行呢?满足了2个条件,首先我们用的是script.src发送的请求,第二个服务器返回的content-type写的是JavaScript类型,这代码自然会执行
///这是后端的
if (path === '/pay'){
  var amount = fs.readFlieSync('./db','utf-8')
  var newAmount = amount - 1
  fs.writeFlieSync('./db',newAmount)
response.setHeader('Conten-Type','application/JavaScript')
response.statusCode = 200
response.write('amount.innerText = amount.innerText - 1')
response.end()
}
//这种技术叫SRJ 服务器-S/返回的-R/JavaScript-J/就是这个意思
//由于script标签是可以跨域的,因此通过SRJ技术就可以实现两个不同域的前端和服务器之间的交流,这区别于以前的同域前端后端交互

现在版本,就是上面的改良版,升级版//利用script标签.src可以访问别的网站这个特性,除非他防盗链

  • 先有jsonp然后才有的ajax
  • 上一个版本的SRJ存在一个代码耦合问题,后端代码控制前端代码,或者说耦合性太强,会导致一个问题, 就是后端必须非常了解前端,甚至于要了解到页面上的细节,就如展示的上个版本SRJ代码,就存在这个问题,如果是简单的几行代码没什么关系,可是真正的工作中,面临的是庞大的代码量,而且SRJ升级版本是要跨域名请求的,比如一个百度后台程序员,哪里知道腾讯官网前端代码的细节啊~这就存在一个很严重的耦合问题

//如何解决?//解耦啊后端直接调用函数,让前端封装这个函数,并且在发送script请求的时候把这个函数名发送给后端,让服务器知道,这段话才是本节课的重中之重!!!!!!!!!!!!!

//这就意味着,前后端耦合,这就意味着后端必须对前端页面的细节很了解才能写出很好的响应,这不好!就像一个百度前端访问腾讯的后端,细节不了解就意味着难以解决两个网站之间的交流问题,因为耦合,必须腾讯后端很了解百度前端代码,这是不靠谱的
//这段话什么意思?

  • 由于前面的打好了基础:script可以跨域请求,后端返回字串,因为返回的是script字串,所以前端会执行这些script字串
  • 为了前后端解耦,使得两个网站更好交流,就让前端封装好一个函数,并且告诉后端这个函数名,后端返回的字串就是执行这个函数的script字串,这样做的好处就是解耦,后端不用了解前端任何细节,返回一个执行的函数就ok了
  • 前端如何告诉后端这个callback函数的呢?
    //传参啊 src="http//www.baidu.com/pay?callbackName=xxx"
  • 后端怎么获取这个callback函数的呢?
    // ${query callback}.call(undefined,'成功或者失败')
  • 这个callbackName就是程序员之间的约定俗成
    //补充一点,浏览器提供了onloading和result 这些接受结果的api
  • 终于知道什么是jsonp了,jsonp其实就是两个不同域之间的网站交流,服务器返回的数据用json语法写,所以叫做jsonp,服务器返回的是符合JSON语法的一串字符串,这才是本质

Jsonp就是解决两个网站之间,的交流问题~老方把这技术叫:动态标签跨域请求

总结,JSONP是怎样的一种技术:

请求方:frank.com 的前端程序员(浏览器)
响应方:jack.com 的后端程序员(服务器)

请求方创建 script,src 指向响应方,同时传一个查询参数 ?callbackName=yyy
响应方根据查询参数callbackName,构造形如
yyy.call(undefined, '你要的数据')
yyy('你要的数据')
这样的响应
浏览器接收到响应,就会执行 yyy.call(undefined, '你要的数据')
那么请求方就知道了他要的数据
这就是 JSONP

callbackName这个名字,是行业约定俗成的
yyy这个函数名是随意起的,因为可能请求多个网站啊,为了不重复就用了一个随机数,来做函数名

完整实现一次JSONP的代码,以便温习

button.addEventListener('click', (e)=>{
    let script = document.createElement('script')
    let functionName = 'frank'+ parseInt(Math.random()*10000000 ,10)
    window[functionName] = function(){  // 每次请求之前搞出一个随机的函数
        amount.innerText = amount.innerText - 0 - 1
    }
    script.src = '/pay?callback=' + functionName
    document.body.appendChild(script)
    script.onload = function(e){ // 状态码是 200~299 则表示成功
        e.currentTarget.remove()
        delete window[functionName] // 请求完了就干掉这个随机函数
    }
    script.onload = function(e){ // 状态码大于等于 400 则表示失败
        e.currentTarget.remove()
        delete window[functionName] // 请求完了就干掉这个随机函数
    }
})
//后端代码
...
if (path === '/pay'){
    let amount = fs.readFileSync('./db', 'utf8')
    amount -= 1
    fs.writeFileSync('./db', amount)
    let callbackName = query.callback
    response.setHeader('Content-Type', 'application/javascript')
    response.write(`
        ${callbackName}.call(undefined, 'success')
    `)
    response.end()
}
...

课后思考:

  • 除了课堂展示几个标签,还有哪些标签是可以发送请求?
  • 什么是同源策略?
  • 为什么标签只能发送get请求?
  • JSONP技术意义何在?
  • AJAX JSONP具体使用?

你可能感兴趣的:(高级课程jsonp2.0)