Cross-domain principle jsonp

jsonp cross-domain principle: https://www.cnblogs.com/willing-shang/p/6719875.html

 

1 Introduction


jsonp is a common means of cross-domain, and reverse proxy server to do cross-domain process compared to, jsonp even more convenient and lightweight, they have been used to process a large number of cross-domain requests, then this request is way in the end What black magic, make us a headache to solve cross-domain problems.

2. Principle


jsonp in fact, no use of black magic, to achieve this effect cross-domain, using the script tag itself is nothing more than cross-domain capability. We know, img, script, this label if there is a corresponding src, then it will initiate a htttp request to request the appropriate resources, if there is a script tag corresponding path is a js file, then after the download is complete this will immediately js carried out

<script type="text/javascript" src="www.somewhere.com/test.js"></script>
<! - this time will initiate a request to get test.js, after the download is complete will be executed immediately test.js ->


Suppose we need from 'www.localhost.com' to initiate a request for acquiring data 'www.somewhere.com/getdata', if we have to initiate ajax request, because the browser homologous protection limits policy, the request the return value will not be accepted by the browser, which is cross-domain problem. But this script tag will initiate a get request, and the request is not subject to the same origin policy restrictions, and if there is we will 'www.somewhere.com/getdata' to the script tag to send a request to become the following way, it is not there would be no cross-domain problem

 

<script type="text/javascript" src="www.somewhere.com/getdata"></script>
<! - need a script to initiate a get request ->




The answer is yes, and this is the principle of cross-domain jsonp. At the same time, however, there have been two problems here, first, how to use the script to send the request, a second request to obtain the data to be received and processed on how front page. For the first question, we generally will write the script tag in the html document, when we usually encounter will be the dynamic requests, if we have the same as the original written in html tags in advance, the browser parses the document when this script tag will immediately initiate the request, such as when we want to use these data, look for good load data front, this is clearly too time-consuming, less flexible, and the page if there are many requests, would not to advance these many script tag on the page, this page ugly simply can not read. What we need is when requesting service, and then initiate the request, then we can use dynamic tags to achieve, Tondo document.createElement to create a dynamic script tag, and then set its src attribute, etc. after the request is completed and then the script remove the label, then the first problem will be solved.

 

let script = document.createElement('script');
srcipt.src =  'www.somewhere.com/getdata';
document.querySelector('head').appendChild(script);




But at the same time, it also had a second question, how do we know when the request is completed, the request back to how data is processed and, after completion of the request how to remove the label. As mentioned earlier too, after the script tag will be downloaded immediately executed (async and defer temporarily refrain), and our request typically returns a json object but json direct execution to an error, such as { "name": "Liu Hou light", "job": "FE"} If the braces in the statement sentence, the contents of the braces will be recognized as a statement block, the outer layer of braces are simply ignored, if it is {. name: 'Liu Hou light', job: 'FE'} this form may not error, because even ignore the curly braces, name: 'Liu Hou light' is a legitimate js statement, called the label statement, but as there are statements to the label in quotes, "name": "Hou Liu light", but this form is not legal, because the label statement can not be quoted, but the key json but must be enclosed in double quotes, so the direct return a json is not enough, we must return to a job executable js statement. And in general we need to request the results of logical operations to perform some js, then we write logic operations where, how results are returned with the combination of it? This time it needs callback played. We can request the results of "packaging" look, the processing logic data is written to a function, then the result of the script to call this function, the data needs to be passed to this function, then all problems can be solved. Suppose request result content is { "name": "Hou Liu light", "job": "FE"}, the result of the processing function is called callback

// result of processing, callback function, or assignment must have been declared in the page before the script request
function callback (data) {
console.log(data.name)
}
 
 
// Note, script must return a js file, as is the callback function will wrap up the results of the request form in the form of a function call
// document content
callback({ "name": "柳轻侯", "job": "FE"})


However, if multiple jsonp request page, we can not call all the callback function callback it, so this time you need to specify the name of the callback function, different jsonp request call different callback function. Request by the script function name passed to the server, and the server corresponding to the result of this function with the package name, and then return to the front end, so that you can call by name. We will make the request in a simple package.

function getJSONP (url, callback) {
let script = document.createElement('script');
script.type=  "type="text/javascript;
srcipt.src = url +  '?callback=' + callback;
document.querySelector('head').appendChild(script);
}


If this time there are two requests require processing, "www.somewhere.com/getdata1" and "www.somewhere.com/getdata2" two requests require processing results of the request are { "name": "Light Liu Hou" , "job": "FE"} and { "name": "days Tang", "job": "fe"}, handlers are dealData1 and dealData2, how do we deal with?

 

function getJSONP (url, callback) {
let script = document.createElement('script');
script.type=  "type="text/javascript;
srcipt.src = url +  '?callback=' + callback;
document.querySelector('head').appendChild(script);
}
 
const dealData1 = function (data) {
the console.log ( 'which is getData1 callback:' + data.name);
}
const dealData2 = function (data) {
the console.log ( 'which is getData1 callback:' + data.name);
}
 
// request are transmitted
getJSONP( 'www.somewhere.com/getdata1', 'dealData1'); // www.somewhere.com/getdata1?callback=dealData1
getJSONP( 'www.somewhere.com/getdata2', 'dealData2'); // www.somewhere.com/getdata1?callback=dealData2



// 请求结果分别是
dealData1({ "name": "柳轻侯", "job": "FE"})
dealData2({ "name": "天棠", "job": "fe"})
 
//执行结果
这是getData1的回调: 柳轻侯
这是getData2的回调: 天棠




这时候两个结果会分别用传过去的callback来包装,然后输出不同的结果,这时候我们的需求基本上被满足了,最后还要处理的一点,每发一条请求,页面上被凭空创建了一个script标签,如果有请求很多,那么页面上就会多出很多无意义的标签(请求结束之后相应的标签就失去了意义),所以我们需要在请求处理结束之后清除创建的script标签。但是页面上还有别的script标签,必须只清除当前请求的jsonp生成的标签,如果将其他的script标签,可能就会造成其他的严重问题。由于每个jsonp的回调函数名称不一样,我们可以通过回调函数名来找出我们想要清除的script。

const dealData1 = function (data) {
console.log('这是getData1的回调:' + data.name);
// 处理完毕之后清除相应的script标签
let callbackName = arguments.callee.name;
document.querySelector('script[src*="callback=' + callbackName + '"]').remove();
}

3. jsonp的缺点

      • 只能发送get请求。因为script只能发送get请求
      • 需要后台配合。此种请求方式应该前后端配合,将返回结果包装成callback(result)的形式。

Guess you like

Origin www.cnblogs.com/bydzhangxiaowei/p/11622481.html