面试必问之JSONP

我的笔记,暂时没有附带源代码,见谅。
第一部分阐述什么是JSONP,附带面试题一个。
第二部分是发展历程,img法,script法,JSONP法。没有源代码阅读会笔记困难,再次见谅。
第三部分随笔记录一些基础知识。javascript


JSONP

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

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

这就是 JSONP
约定:前端

  1. callbackName -> callback
  2. yyy -> 随机数 好比xxx123145123()

面试题:

请问JSONP为何不能发POST请求?
第一句话: 由于JSONP是经过动态建立script实现的。
第二句话: 动态建立script的时候只能用GET,不能用POSTjava


  • img更新法:用img悄无声息地建立一个请求。只能get,不能post。 若是状态码是2XX就是请求成功,3xx是重定向,4xx就是客户端错误,5xx是服务器错误。
button.addEventLister('click', (e)=>{
    let image = document.creatElement('img')
    img.src = '/pay'
    image.onload = function(){ // 状态码是 200~299 则表示成功
        alert('打钱成功')
        amount.innerText = amount.innerText - 1
    }
    image.onerror = function(){ // 状态码大于等于 400 则表示失败
        alert('打钱失败')
    }
})
复制代码
  • script请求法(SRJ):比img请求法更快;浏览器会执行script的内容即浏览器返回的内容,因此就不须要onload、onerror了;
    SRJ: server rendered JavaScript 服务器返回的js,这是AJAX出来前的无刷新局部更新页面内容的方案。
           特色:script可使用另外一个网站的JS。
<script>
button.addEventLister('click', (e)=>{
    let script = document.creatElement('script')
    script.src = '/apy'
    // 只这样作是不行的。必须把下句代码放在body里才能够,不能放在js文件
    // 只有把下句代码放在页面里,浏览器才会发请求
    document.body.appenChild(script)
    script.onerror = function(){
        alert('打钱失败')
    }
})
</script>

index.js:
response.write(`amount.innerText = amount.innerText - 1`)
复制代码

可是每次打钱成功都会建立一个script,html就变的很丑,因此咱们要打钱成功或失败后删除这个动态建立的script:node

//只需监听script的onload和onerror,都删除这个script便可
script.onload = function(){
    e.currentTarget.remove()
    }
script.onerror = function(){
    alert('打钱失败')
    e.currentTarget.remove()
}
复制代码

script请求法过程描述:jquery

若用户点击了打钱的按钮,就建立一个script,script的src就是要请求的路径,而后把script放到页面里,这样浏
览器就会去发起这个路径的get请求;若是get成功了,它首先会执行服务器返回的js的响应,这个响应就是操做页面局
部的刷新,为何会把响应当成script执行呢?一是由于咱们设置的response.setHeader就是application/java
script;二是我前端确实把它放在script标签里的。执行以后,用户就看到金额减小了,减小以后咱们就去监听,
不管成功失败,都会删除这个script。
复制代码

可是

若是A网站的程序员要去调用B网站的JS,就必须对B网站的页面细节知道的很清楚,不然接口就对不上,这样耦合太大了!因此咱们要解除耦合!程序员

方法:我调用个函数就好了,我不关内心面是什么面试

response.write(`amount.innerText = amount.innerText - 1`) 
改为
response.write(`xxx.call(undefined,'打钱成功'`) 
同时在A网站JS里,监听xxx函数。
复制代码

这个函数名xxx双方是怎么传递的呢?ajax

A:script.src='http://B.com/pay?callback=xxx'
B:response.write(`$(query.callback).call(undefined,'打钱成功'`) 
复制代码

代码细节1: json

JSONP

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

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

这就是 JSONP
约定:

  1. callbackName -> callback
  2. yyy -> 随机数 好比xxx123145123()
functionName = 'om'+parseInt(Math.random()*100000,10)
window[functionName] = function(result){...}
script.src = 'http://jack.com:8002/pay?callback=' + functionName
复制代码

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.onerror = 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()
}
复制代码

写了这么多,jQuery已经帮咱写好了!!!!!

代码原网站

button.addEventListener('click', (e)=>{
     $.ajax({ // 这个名字跟ajax没有半毛钱关系,ajax是ajax,jsonp是jsonp
     url: "http://jack.com:8002/pay",
     dataType: "jsonp",
     success: function( response ) {
         if(response === 'success'){
         amount.innerText = amount.innerText - 1
         }
     }
     })
    
     $.jsonp()
})
复制代码

面试题:

请问JSONP为何不能发POST请求?
第一句话: 由于JSONP是经过动态建立script实现的。
第二句话: 动态建立script的时候只能用GET,不能用POST


  • onload:onload 事件会在页面或图片加载完成后当即发生。
  • onerror:onerror 事件会在文档或图像加载过程当中发生错误时被触发。 在装载文档或图像的过程当中若是发生了错误,就会调用该事件句柄。
  • alert():显示一个警告对话框,上面显示有指定的文本内容以及一个"肯定"按钮。
  • Location.reload():用来刷新当前页面。
           该方法只有一个参数,当值为 true时,将强制浏览器从服务器加载页面资源,当值为 false 或者未传参时,浏览器则可能从缓存中读取页面。
           该方法在跨域调用(执行该方法的脚本文件的域和 Location 对象所在页面的跨不一样)时,将会抛出 DOMException 异常。
  • ASP Response 对象:于从服务器向用户发送输出的结果。ASP其他对象参考连接 response.write():向输出写指定的字符串。
    response.end():中止处理脚本,并返回当前的结果。
    response.setHeader(name, value):例如response.setHeader('Content-Type', 'text/html');
    response.statusCode = 2xx/3xx/4xx/5xx :此属性控制在刷新响应头时将发送到客户端的状态码。
  • node.js:Node.js就是这样一个服务器端的、非阻断式I/O的、事件驱动的JavaScript运行环境。(去茶叶铺卖茶叶例子)
    Node.js的应用是经过javascript开发的,而后直接在Google的变态V8引擎上跑。用了Node.js,你就不用担忧用户端的请求会在服务器里跑了一段可以形成阻塞的代码了。由于javascript自己就是事件驱动的脚本语言。
           服务器端JavaScript处理:server-side JavaScript execution
           非阻断/异步I/O:non-blocking or asynchronous I/O
           事件驱动:Event-driven
  • 占位符:&&&amount&&& 这是一个特殊的占位符,总体都是,为了表示这是个人占位符,别人别碰。
  • fs: fsfilesystem的缩写,该模块提供本地文件的读写能力,基本上是POSIX文件操做命令的简单包装。可是,这个模块几乎对全部操做提供异步和同步两种操做方式,供开发者选择。 FS讲义 FS文档
异步 fs.readFile(文件的路径, 读取完成后的回调函数)
同步 fs.readFileSync(文件路径,'utf8')

     fs.readFileSync()的第二个参数能够是一个表示配置的对象,也能够是一个表示文本文件编码的字符串。
     默认的配置对象是{ encoding: null, flag: 'r' },即文件编码默认为null,读取模式默认为r(只读)。
     若是第二个参数不指定编码(encoding),readFileSync方法返回一个Buffer实例,不然返回的是一个字符串。
     
     Buffer对象是Node处理二进制数据的一个接口,它是Node原生提供的全局对象,能够直接使用。
     buffer文档:https://javascript.ruanyifeng.com/nodejs/buffer.html

复制代码
  • form(html标签): 一旦提交,就刷新当前页面
action="URL" 规定当提交表单时向何处发送表单数据。
method="get/post" 规定用于发送 form-data 的 HTTP 方法。 
target="" 规定在何处打开 action URL。
复制代码
  • input: 用于搜集用户信息。根据不一样的 type 属性值,输入字段拥有不少种形式。输入字段能够是文本字段、复选框、掩码后的文本控件、单选按钮、按钮等等。 value="xxx" 规定input元素的值是xxx
相关文章
相关标签/搜索