Resolves the error that jquery uses when using JSONP _jquery

Source: Internet
Author: User
Tags error handling parse error

What is a domain , in simple terms is the protocol + domain name or address + port , 3 if there is any one difference will mean not the same domain. Cross-domain is the data that accesses another domain in one domain.

If you just load the contents of another domain without having to access the data in it, the cross-domain is simple, such as using an iframe. But if you need to load and use the data from another domain, it can be tricky. For security purposes, browsers have strict restrictions on the situation, requiring both client and server settings to implement Cross-domain requests.

JSONP Introduction
JSONP(JSON with Padding) is a commonly used Cross-domain method, but only supports JS script and JSON-formatted data. As the name suggests,JSONP is a technical means of using JSON as a gasket to achieve cross-domain requests. The basic principle is that HTML <script> tags are inherently cross-domain, with which you can load the JSON data for another domain, and then automatically run a callback function to notify the caller when the load is complete. This process requires server-side support for another domain, so the cross-domain implementation of this approach is not arbitrary.

jquery's support for JSONP
jquery's Ajax object supports JSONP Cross-domain requests by specifying the Crossdomain parameter as true and specifying the dataType parameter as jsonp[1], or by using the shorthand form: Getjson () method [2 ]。 For example:

Set the Crossdomain and DataType parameters to use Jsonp
$.ajax ({
 dataType: "Jsonp",
 URL: "Http://www.example.com/xxx",
 crossdomain:true,
 data: {
  
 }
}). Done (function () {
 //processing functions at request completion
});

Use Getjson
$.getjson ("http://www.example.com/xxx?jsoncallback=?", {
 //parameter
}, function () {
 // The processing function at the time the request completes
});

When using Getjson , you need to specify jsoncallback= in the parameter, which is the callback function mentioned earlier, and jquery automatically replaces the question mark part of the argument with a randomly generated value (the callback functions name) to form Jsoncallback=jqueryxxxxxxx This form of the argument, and then use the Get method to make the request with the other parameters.

When you use the first method, specifying the value of the dataType parameter as Jsonp,jquery automatically adds the Jsoncallback parameter after the request address, so you do not need to add it manually.

jquery cross-domain request flaw: error handling
cross-domain requests may fail, such as the security settings of the opposing server refuse to accept requests from us (we are not in the other person's trust list), or the network is not connected, or the other server has been shut down, or the request address or parameters are incorrect to cause the server to complain and so on.

In jquery, a Jqxhr object [3] is returned when a request is sent using AJAX or Getjson. The object implements the Promise protocol, so we can use its done, fail, always interfaces to handle callbacks. For example, we can use error handling when a request fails in its fail callback:

var xhr = $.getjson (...);
Xhr.fail (function (JQXHR, Textstatus, ex) {
  alert (' request failed, cause: ' + ex.message);
});

This approach is capable of handling "normal errors" such as timeouts, requests being aborted, JSON parsing errors, and so on. However, it is not good for those "abnormal errors", such as network impassability, server shutdown and so on.

For example, you will see an error message in the console under Chrome when the opposing server is not properly accessed:

jquery does not deal with this error, but chooses to "silently fail": Thefail callback does not execute and your code does not receive any feedback, so you do not have the opportunity to handle the error or report the error to the user.

One exception is in IE8. In IE8, when the network is inaccessible, the ,<script> tag returns information about the success of the load, so jquery cannot determine whether it was loaded successfully based on the state of the <script> tag, but it found <script The callback function is not executed after the > tag is "loaded successfully", so jquery determines that this is a "parse error" (The callback code is not executed, most likely the returned data does not result in no execution or execution failure), so the error message returned will be "XXXX is not called", Where the xxxx is the name of the callback function.

In other words, because IE8 (IE7 also) of this wonderful characteristics, resulting in network impassability and other "abnormal error", jquery could not choose "silent failure" strategy, so we can benefit from the opportunity to deal with the error. For example, in this case, the above example will pop up the "xxxx is not called" dialog box.

Solution
When you encounter an "abnormal error", jquery's Jsonp will "fail silently" in newer browsers, except for IE7, 8. But most of the time we want to be able to catch and handle this error.

In fact, in these browsers the,<script> tag triggers an error event when these errors are encountered. For example, if we were to implement JSONP ourselves, we could do this:

var ele = document.createelement (' script ');
Ele.type = "Text/javascript";
ELE.SRC = ' ... ';
Ele.onerror = function () {
  alert (' Error ');
Ele.onload = function () {
  alert (' Load ');
Document.body.appendChild (ele);

In a new browser, an error event will be triggered to execute the OnError callback pop-up Alert dialog box when a failure occurs:

But the trouble is, jquery won't expose this <script> tag to us, so we don't have a chance to add onerror event handlers to it.

Here is the main code for jquery implementation JSONP :

Jquery.ajaxtransport ("Script", function (s) {
 if (s.crossdomain) {
  var script, head
   = Document.head | | jquer Y ("head") [0] | | document.documentelement;
  return {
   Send:function (_, callback) {
    script = document.createelement ("script");
    Script.async = true;
    ...
    SCRIPT.SRC = S.url;
    Script.onload = Script.onreadystatechange = ...;
    Head.insertbefore (script, head.firstchild);
   },
   abort:function () {
    ...
   }
}};

You can see that the script is a local variable that cannot be retrieved from the outside.

Is there any way to solve it? Of course:

    • Implement JSONP yourself, without using jquery
    • Modify the jquery source code (if you are not using the CDN way to reference jquery)
    • Use the tips presented in this article

The first two do not say, if you are willing to big can choose. Here's another tip.

Through the above source can be found, jquery although did not expose the script variable, but it is "exposed" the location of the <script> tag. Through the last sentence of the Send method:

Head.insertbefore (script, head.firstchild);
You can see that this dynamically created new creation tag is added as the first element of the head. And we do the opposite, as long as we can get the head element, we can get this script? What's head? Continue to look at the source, see how head is coming:

Head = Document.head | | JQuery ("Head") [0] | | Document.documentelement;
So, we have the same way to get it, so fill in the previous example, as follows:

var xhr = $.getjson (...);
For "normal error" and IE 7, 8
xhr.fail (function (JQXHR, Textstatus, ex) {
  alert (' request failed, cause: ' + ex. message);
For ' abnormal error ' in the other browsers
var head = Document.head | | $ (' head ') [0] | | document.documentelement;//CO De from jquery
var-script = $ (head). Find (' script ') [0];
Script.onerror (function (evt) {
  alert (' Error ');
});

This allows us to catch "abnormal errors" in all browsers (strictly speaking, because I have not tested all browsers).

This is also a benefit of capturing errors: in browsers other than IE7, 8, when there are problems with network failure, jquery, in addition to failing silently, will leave a heap of rubbish to be removed, namely the newly created <script> tags and global callback functions. It's no big harm to stay there, but wouldn't it be better if you could clean it off? So we can achieve onerror:

Handle Error
alert (' Error ');

Do some clean

//Delete script node
if (script.parentnode) {
  script.parentNode.removeChild (script);
}
//Delete jsoncallback global function
var src = script.src | | '';
var idx = src.indexof (' jsoncallback= ');
if (idx!=-1) {
  var idx2 = Src.indexof (' & ');
  if (idx2 = = 1) {
  idx2 = src.length;
  }
  var jsoncallback = src.substring (idx +, idx2);
  Delete Window[jsoncallback];
}

This is perfect.

Complete code

function Jsonp (URL, data, callback) {var xhr = $.getjson (url + '? jsoncallback=? ', data, callback); Request failed Xhr.fail (function (JQXHR, Textstatus, ex) {/* in IE 8, if service are down (or network occur s an error), the arguments would be: * * teststatus: ' parsererror ' * ex.description: ' xxxx is not called '
    (xxxx is the name of Jsoncallback function) * Ex.message: (same as Ex.description) * ex.name: ' Error ' *
  Alert (' failed ');

  }); IE 8+, chrome and some browsers var head = Document.head | | $ (' head ') [0] | | Document.documentelement;
  Code from jquery var script = $ (head). Find (' script ') [0];

    Script.onerror = function (evt) {alert (' Error ');
    Do some clean//delete script node if (script.parentnode) {script.parentNode.removeChild (script); }//Delete jsoncallback global function var src = script.src | |
    '';
    var idx = src.indexof (' jsoncallback= ');
 if (idx!=-1) {     var idx2 = Src.indexof (' & ');
      if (idx2 = = 1) {idx2 = Src.length;
      var jsoncallback = src.substring (idx +, IDX2);
    Delete Window[jsoncallback];
}
  };

 }

The above code in IE8, IE11, Chrome, FireFox, Opera, 360 under test pass, of which 360 is the IE kernel version, other browsers temporarily not tested.

I hope this article will learn from you and help you solve the error of jquery using JSONP.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.