📜 ⬆️ ⬇️

JQuery Deferred - usage examples

In this article I will not talk about why in javascript you need promises, and in particular JQuery.Deferred. Also, I will not give background information, it is enough on the Internet. For example, here or here or here .
This article is for techs who are already a little familiar with the Deferred object from the jQuery library, but have no experience writing complex chains (queues).

Training

All code examples discussed here use the asynchronous $ .ajax () method, which returns the so-called jqXHR in which promis methods are implemented (done, fail, always, then). We will only need them, so we assume that $ .ajax returns a promise.
Some examples use the $ .map () and $ .each () methods that are part of the jQuery library.

Sequential execution

The simplest use of promises is the sequential execution of asynchronous operations. That is, the next operation does not begin until the current one ends.
')
$.ajax('http://echo.jsontest.com/id/1') .then(function(result){ console.log(JSON.stringify(result)); return $.ajax('http://echo.jsontest.com/id/2') }).then(function(result){ console.log(JSON.stringify(result)); return $.ajax('http://echo.jsontest.com/id/3') }).then(function(result){ console.log(JSON.stringify(result)); }); 

A live example is here .

Parallel execution

Starts all asynchronous operations at the same time and proceeds to the next callback only when all parallel operations are completed.

 $.when( $.ajax('http://echo.jsontest.com/id/1'), $.ajax('http://echo.jsontest.com/id/2'), $.ajax('http://echo.jsontest.com/id/3') ).then(function(result1, result2, result3){ console.log(JSON.stringify(result1[0])); console.log(JSON.stringify(result2[0])); console.log(JSON.stringify(result3[0])); }) 

A live example is here .

Sequential parallel execution

Task: to execute one request, and after its completion, to start parallel execution of several more operations.

 $.ajax('http://echo.jsontest.com/id/1') .then(function(result1){ console.log(JSON.stringify(result1)); return $.when( $.ajax('http://echo.jsontest.com/id/2'), $.ajax('http://echo.jsontest.com/id/3'), $.ajax('http://echo.jsontest.com/id/4') ) }).then(function(result2, result3, result4){ console.log(JSON.stringify(result2[0])); console.log(JSON.stringify(result3[0])); console.log(JSON.stringify(result4[0])); }) 

Living example .

Parallel execution of an unknown number of asynchronous operations

Moving on to more difficult situations. Suppose there is an array with links for each of which you need to make a parallel query. The task is complicated by the fact that the number of links in the array is not known in advance.

 array = ['/url1', '/url2', ….. '/urlN'] 

We already know that the $ .when method is used for parallel start as follows:

 $.when(promise1, promise2, … promiseN) 

But, unfortunately, it is impossible to transfer an array of promises to this method. Therefore, this code can be rewritten a little, and then it is suitable for our task:

 $.when.apply(this, [promise1, promise2, … promiseN]) 

But the complete solution of the problem:

 urls = ['http://echo.jsontest.com/id/1', 'http://echo.jsontest.com/id/2', 'http://echo.jsontest.com/id/3'] promises = $.map(urls, function(url){ return $.ajax(url).then(function(result){ console.log(JSON.stringify(result)); }); }); $.when.apply(this, promises) .then(function(){ console.log('done'); }); 

The same code on jsfiddle .

Sequential execution of an unknown number of asynchronous operations

The task is the same as in the previous example, but requests must be sent sequentially. This approach will help if there are a lot of requests, and the server part of the web application is not designed for such loads.
To solve this problem, we will “build up” the chain of promises in the cycle.

 urls = ['http://echo.jsontest.com/id/1', 'http://echo.jsontest.com/id/2', 'http://echo.jsontest.com/id/3'] promise = $.when(); $.each(urls, function(index, url){ promise = promise.then(function(){ return $.ajax(url); }).then(function(result){ console.log(JSON.stringify(result)); }); }); promise.then(function(){ console.log('OK'); }); 

Here I applied a small trick: promise = $ .when (). Running the $ .when method with no arguments will return a resolved promise that will be the first link in the chain.
View code in action.

Simple error handling: one handler for all operations

For error handling, the .fail method is used. In the example below, this method is located at the very end of the promis chain, and if an error occurs, all the completed callbacks are skipped.

 $.ajax('http://echo.jsontest.com/id/1') .then(function(){ console.log('OK 1'); return $.ajax('http://echo.jsontest.com/id/2'); }).then(function(){ console.log('OK 2'); return $.ajax('http://echo.jsontest_fail.com/id/3'); }).then(function(){ console.log('OK 3'); return $.ajax('http://echo.jsontest.com/id/4'); }).then(function(){ console.log('OK 4'); }).fail(function(){ console.log('error'); }); 

Run this code.

Stopping chain execution after error handling

If several error handlers (rejected promises) are used in the chain, then if any errors occur, all subsequent fail callbacks will be called. Example:

 $.ajax('http://echo.jsontest.com/id/1') .then(function(){ console.log('OK 1'); return $.ajax('http://echo.jsontest.com/id/2'); }).then(function(){ console.log('OK 2'); return $.ajax('http://echo.jsontest_fail.com/id/3'); }).fail(function(){ console.log('error 1'); }).then(function(){ console.log('OK 3'); return $.ajax('http://echo.jsontest.com/id/4'); }).fail(function(){ console.log('error 2'); }).then(function(){ console.log('OK 4'); }).fail(function(){ console.log('error 3'); }); 


After executing this code, we will see the following in the console:

 OK 1 OK 2 error 1 error 2 error 3 

Link for those who do not believe.
But most likely this behavior is not useful to us. We will do this so that after processing the error, no subsequent callback will be called.

 $.ajax('http://echo.jsontest_fail.com/id/1') .then(function(){ console.log('OK 1'); return $.ajax('http://echo.jsontest.com/id/2'); }, function(){ console.log('error 1'); return $.Deferred(); }).then(function(){ console.log('OK 2'); }, function(){ console.log('error 2'); }) 

Look at the result .
In this example, two things should be noted. First, error handlers are now specified by the second argument of the .then method. Second, the error handler returns a Deferred object (promise) that is neither resolved nor rejected.

Continuing chain execution after error handling

Slightly changing the previous example can be done so that after processing the error the following done callback will be called.

 $.ajax('http://echo.jsontest_fail.com/id/1') .then(function(){ console.log('OK 1'); return $.ajax('http://echo.jsontest.com/id/2'); }, function(){ console.log('error 1'); return $.when(); }).then(function(){ console.log('OK 2'); }, function(){ console.log('error 2'); }) 

This example differs from the previous one only in the seventh line.

Conclusion

The JQuery.Deferred component is not as complicated as it seems when you first meet it, but the other libraries that implement the functionality of promises are just as simple.

UPD

Thanks to mayorovp for comment

Source: https://habr.com/ru/post/230441/


All Articles