Jquery Ajax Calls to Web Service Seem to Be Synchronous

jQuery Ajax calls to web service seem to be synchronous

This is because you have enable the Session and the Session lock all the calls until they return.

You can read also this question: Replacing ASP.Net's session entirely

also read: https://stackoverflow.com/a/3660837/159270

jQuery: Performing synchronous AJAX requests

As you're making a synchronous request, that should be

function getRemote() {
return $.ajax({
type: "GET",
url: remote_url,
async: false
}).responseText;
}

Example - http://api.jquery.com/jQuery.ajax/#example-3

PLEASE NOTE: Setting async property to false is deprecated and in the process of being removed (link). Many browsers including Firefox and Chrome have already started to print a warning in the console if you use this:

Chrome:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

Firefox:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user’s experience. For more help http://xhr.spec.whatwg.org/

jQuery $.ajax calls executing synchronously instead of concurrently on calls to WCF service

If you are using ASP.NET they use read/write locks on the Session object. This makes AJAX request serial.

In ASP.NET you can have IHttpHandlers that implement IReadOnlySessionState which will not place the read/write lock on Session. Not sure what environment you are using though.

Edit 1

This post seems to indicate that WCF services don't allow you the flexibility to unlock the session:

How to force an IIS hosted WCF or ASMX [webservice] to use session object readonly?

Edit 2

Setting up an IHttpHandler that will not lock the Session object.

Web.config

<configuration>
<connectionStrings>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="MyProvider" path="MyProvider.aspx" verb="*" type="MyNamespace.MyProvider" resourceType="Unspecified" />
</handlers>
</system.webServer>
</configuration>

MyProvider.cs

using System;
using System.Web;
using System.Web.SessionState;

namespace MyNamespace
{
public class MyProvider : IHttpHandler, IReadOnlySessionState
{
public bool IsReusable
{
get { return true; }
}

public void ProcessRequest(HttpContext context)
{
}
}
}

If you want to create a provider that receives and returns JSON objects you can create classes for the Request and Response and then your handler can be set up like this:

MyProvider.cs (processing JSON objects)

using System;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Web.SessionState;

namespace TestWebsite
{
public class MyProvider : IHttpHandler, IReadOnlySessionState
{
public bool IsReusable
{
get { return true; }
}

public void ProcessRequest(HttpContext context)
{
var response = new Json.Response();
try
{
var requestSerializer = new DataContractJsonSerializer(typeof(Json.Request));
var request = (Json.Request)requestSerializer.ReadObject(context.Request.InputStream);

// ...
}
catch (Exception ex)
{
response.Error = ex.ToString();
}

try
{
var responseSerializer = new DataContractJsonSerializer(typeof(Json.Response));
context.Response.ContentType = "application/json";
responseSerializer.WriteObject(context.Response.OutputStream, response);
}
catch (Exception)
{
throw;
}
}
}
}

Multiple Ajax calls appear to be treated as synchronous requests when they should not be

It appears that your first ajax request is setting async flag to false. You can change that call to following

$.ajax({
type: 'GET',
async: true,
url: '/widgets/test',
success: function (response) {
$("#widgetData").val(JSON.stringify(response));
$("#widgetData").trigger("change");
},
error: function (xhr, textStatus, errorThrown) {
console.log("There was a problem requesting the widget endpoint!");
}
});

This should fix your warning message

How can I call ajax synchronously without my web page freezing

You can put in in a function that performs the next call, and call this from your success handler, like this:

$(function(){ 
var i = 0;
function nextCall() {
if(i == a.length) return; //last call was last item in the array
$.ajax({
url:'/this-script-takes-a-few-seconds-to-complete.php',
data: { foo: a[i++] },
success: function(data){
console.log(data);
nextCall();
}
});
}
nextCall();
});

Though...the better approach would be to not do 100 calls, unless this is a test suite of some-sort, I'd re-visit the whole approach.

How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?

From the jQuery documentation: you specify the asynchronous option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.

Here's what your code would look like if changed as suggested:

beforecreate: function (node, targetNode, type, to) {
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
}

synchronous ajax call - show div before call

A workaround is to use the function below that allows a "loading screen" to be displayed on the system when we make synchronous calls ("ajax"). It can be easily adapted for use with legacy codes.

Realize that "ajax" blocks the modification of the "DOM" even though IT IS EXECUTED BEFORE THIS CALL. This approach will ONLY WORK if it is used at the FIRST TIME of a process that involves some sync ajax call before. Basically, it creates a time window (50 ms) for updating the DOM before executing the desired function/method ("appFunc"). The use of this function only makes sense in situations that require the use of the sync ajax call output immediately after its execution.

EXAMPLE OF USE: <button type="button" onclick="opSyncLoading(login, [this.form])">

  • In this example we take advantage of the "eventuality" of the user action to create a time window to the thread and display the "loading screen". Note that the "login" function does not return any type of output. Note that everything that happens after "login" function will be done in a "SYNC" way.
  • This limitation is due to the fact that the JS/DOM has only one "thread" to handle everything, that is, there is no way to wait with a "sleep", for example, since no type of effective parallelism exists. One solution could be to use "web worker", but this is outside the scope of the question presented.
  • The use of synchronous "ajax" calls MUST be avoided because since it causes side effects to the operation of JS and HTML responsiveness besides being seen as bad practice. Its use should be limited to legacy codes or situations where it is strictly necessary.

TIP: Note that if there is an animated gif on the "loading screen" it will be "locked" until the "ajax" call is completed, however in some modern browsers this problem does not happen. In extreme case there is a possibility that the image will remain "animated" if it is loaded in an iframe (https://stackoverflow.com/a/16704839/3223785).

function opSyncLoading(appFunc, appFuncArgs) {
if (typeof appFuncArgs === "undefined" || appFuncArgs === "") {
appFuncArgs = [];
}
$("#loadingDiv").fadeIn(500, setTimeout(function () {

// NOTE: Passing unknown arguments in quantity and nature to a callback function. By Questor
// [Ref.: https://stackoverflow.com/a/49680525/3223785 ]
appFunc.apply(this, appFuncArgs);

}, 50));
}

Thanks! =D

Ajax calls from browser over Asynchronous Controller

AsyncController was not designed for the purpose of serving HTTP requests asynchronously, but for the purpose of executing long running server-side processes. Making a single request to REST service may or may not be a long running server-side process.

So, whether you decide to make the REST request server-side or directly from the client (browser), you do not necessarily need to use an AsyncController. A normal Controller might do the job.

How you should handle the video requests depends on how your business layer is structured. If there is knowledge of the Vimeo videos for processing in the business layer, then it is best practice to make your web-service calls service side. Otherwise, you have business logic on your client, which can make things difficult to maintain.

If on the other hand, your Vimeo videos are only part of a self-contained UI-widget, then it is safe to process the request completely on the client without incurring unexpected consequences.

I am assuming the web-service call to Vimeo receives a Flash file or something like it. It would require more bandwidth as well as cost more memory to make the Vimeo service calls from the server, because then the data has to go to your server.

If you do it server side, this happens:

 1 - Browser sends HTTP-Request to YourApplication
2 - YourApplication sends HTTP-Request to Vimeo's WebService
3 - Vimeo's WebService sends big HTTP Response with the Video data to YourApplication
4 - YourApplication sends big HTTP Response with the Video data to Browser

* If you choose to do it this way, this might be the point at which it makes sense to use an AsyncController

If you do it client side, this happens:

 1 - Browser sends HTTP-Request to Vimeo's WebService
2 - Vimeo's WebService sends big HTTP Response with the Video data to the Browser

This makes it look like doing it all client-side is better. But then there is the whole business logic issue. This can be remedied by sending an ajax request to a synchronous controller action to do business logic processing, and having it return the URL of the call to the REST service to the browser. So:

 1 - Browser sends AJAX request to YourApplication
2 - YourApplication handles business logic and sends the URL of the REST request to Browser
3 - Browser sends AJAX request to Vimeo's WebService
4 - Vimeo's WebService sends big HTTP response with the video data to the browser.

I think this is probably your best bet.



Related Topics



Leave a reply



Submit