0

I have a simple ajax function:

function GetJsonData(api) {

 return (
 $.ajax({
 type: 'GET',
 jsonpCallback: 'callback',
 url: api,
 dataType: 'jsonp'

 }));
}

and now when I tried to do multiple calls like this:

 $.when(
 GetJsonData("api"),
 GetJsonData("api"),
 GetJsonData("api"),
 GetJsonData("api"),
 GetJsonData("api")
 )
 .done(function (data1, data2, data3, data4, data5) {
 alert("success");

 })
 .fail(function () {
 alert("fail");
 });

Each time when I do calls like above, I mostly get Failed alert. Only sometime I get Success alert.

But when I do not more than 2 calls at same time in $.when, then I will always get Success alert.

Can anyone please help me to find out where I m wrong in the above code snippets? OR I have to use another approach to make the above function work properly.

Ammar Khan
  • 13
  • 4

2 Answers2

2

The problem is that you're forcing jQuery to use a specific JSONP callback function name, callback, with this option:

jsonpCallback: 'callback'

So if you have overlapping JSONP calls, jQuery will try to use the same function on your page to handle the result of each of them, and remove the function once it's done its job for a request. This is obviously a bit of a problem, the requests stomp on each other.

Remove that option and allow jQuery to create its own function name. It will ensure the function name is unique to each request.


In the comments below you've said:

When I remove the jsopCllback parameter I mreceving this error in browser ReferenceError: callback is not defined

and that what you see come back when you remove the jsonpCallback: 'callback' argument is:

callback( { "status": 0, "item": 20, "contents": [ { "new1": 196, "new2": 1, "new3": 2, "new4": "abcd", "new5": 41, "new6": "aadsa", } ] }

That means JSONP service you're talking to uses a non-standard query string argument name for the name to give the callback, and so it's ignoring the standard one that jQuery uses. You'll have to find out what argument name they expect the callback name in, and use the jsonp: 'argNameTheyUse' option for ajax.

The standard argument name is callback, e.g.:

http://example.com/getsomething?callback=foo

...means to use the callback name foo. But some APIs use a different argument, such as:

http://example.com/getsomething?mySpecialCallbackArg=foo

If you were calling that endpoint, you'd need the jsonp: 'mySpecialCallbackArg' option on ajax.


In the further comments, you say you can't point to the API documentation becuase it's "private." If it's "private" as in it's something you or your company control, then great, fix it so it respects the callback query string argument and uses that as the function name in the JSONP response. That's how JSONP is meant to work.

E.g., if you send it this request:

http://example.com/getsomething?callback=foo

...have the code generating the response use foo as the JSONP callback name:

foo({
   "data": "here"
})

If the query is:

http://example.com/getsomething?callback=bar

Then use bar instead:

bar({
   "data": "here"
})

That way, when you make multiple overlapping calls, jQuery can give a unique function to each of them, and they don't end up stepping on each other.

If for some reason you can't do that (?!), then you'll have to make your calls in series (one after another) instead of in parallel.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you very much for pointing out a mistake, but let me tell you something If I remove the jsonpCallback: 'callback' from the function then I will not get any of the alert "success" or "fail". It may be because all api's return the result inside the callback wrapper. Any suggestion what I have to do in this case? – Ammar Khan May 17 '13 at 09:46
  • @AmmarKhan: That's *very* surprising. Please create a [small, self-contained, correct example](http://sscce.org) demonstrating the problem (including the JSONP API you're calling) and post it to the question. (And optionally *also* to http://jsbin.com or http://jsfiddle.net.) – T.J. Crowder May 17 '13 at 09:47
  • 1
    @AmmarKhan: Also, when it fails, what do you see in your browser's debugger's Network tab? (If your browser doesn't have one, switch to a modern browser.) – T.J. Crowder May 17 '13 at 09:48
  • callback( { "status": 0, "item": 20, "contents": [ { "new1": 196, "new2": 1, "new3": 2, "new4": "abcd", "new5": 41, "new6": "aadsa", } ] } – Ammar Khan May 17 '13 at 09:50
  • When I remove the jsopCllback parameter I mreceving this error in browser ReferenceError: callback is not defined – Ammar Khan May 17 '13 at 09:54
  • @T.J.Crowder I've looked in the jQuery source and AFAICS it never deletes the old callback from `window`, it restores the previous value. However the installed function is lexically bound to per-call state, so replacing it will very likely as you suggest mess with the calls. They really ought to warn against that... – Alnitak May 17 '13 at 09:54
  • @AmmarKhan: Then the JSONP endpoint you're talking to has a non-standard query string argument for the name to give the callback. You'll have to find out what argument they expect the callback name in, and use the `jsonp: 'argNameTheyUse'` option for `ajax`. The standard argument is `callback`, e.g., `http://example.com/getsomething?callback=foo` means to use the callback name `foo`. But some APIs use a different argument, such as `http://example.com/getsomething?mySpecialCallbackArg=foo` instead. – T.J. Crowder May 17 '13 at 09:55
  • @T.J. Crowder: But In my case there is not special argument, I m using the standard argument name which is http://example.com/getsomething?callback=callback – Ammar Khan May 17 '13 at 10:07
  • @AmmarKhan: If you're going to have overlapping requests, you **must** use a different function name for each request. In JSONP, the name of that function is controlled by a query string argument. The standard query string argument name is `callback` (this is also the default callback name, but I'm talking about the *argument name*, not the *function* name). jQuery uses that standard query string argument, for instance: `http://example.com/getsomething?callback=_jquery1212321`. Since your service is not using the callback jQuery defines, it must be using a *different* name for the *argument*. – T.J. Crowder May 17 '13 at 10:10
  • @AmmarKhan: See my question on the question: What API are you using? I bet we could resolve this in about two minutes if you'd tell us. – T.J. Crowder May 17 '13 at 10:11
  • Can you send me your email address, I can not publish the api here. – Ammar Khan May 17 '13 at 10:17
  • @AmmarKhan: No, we keep these things on-site. If it's a public API, what's the problem? – T.J. Crowder May 17 '13 at 10:18
  • it's not a public API .Actually it's private and I can not share the username and password here – Ammar Khan May 17 '13 at 10:19
  • @AmmarKhan: I didn't ask you to. I asked you to point to the documentation. If it's "private" as in it's something you or your company control, then great, fix it so it respects the `callback` query string argument and uses that as the function name in the JSONP response. That's how JSONP is meant to work. (See further update to the answer.) – T.J. Crowder May 17 '13 at 10:46
  • @T.J. Crowder: Thank you so much for all your help, I m trying to fix the callback query string argument. If need your help again I will come back to you.OK – Ammar Khan May 17 '13 at 11:05
-1

it may happen because you are calling multiple ajax call parallelly and ajax is asynchronous.

Jaid07
  • 153
  • 1
  • 4
  • yes of course it is asynchronous, i have also wrote asynchronous not synchronous!! – Jaid07 May 17 '13 at 09:54
  • it may be one of the issue as in my earlier development i faced this issue, that's why i posted. and i have not edited my post, you missed "a" :) – Jaid07 May 17 '13 at 10:11