美文网首页
高级课程jsonp2.0

高级课程jsonp2.0

作者: joker731 | 来源:发表于2018-02-04 22:26 被阅读30次

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

    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

          本文链接:https://www.haomeiwen.com/subject/zrwnnxtx.html