Use Promise of jQuery and jQueryPromise
Promise has been widely used in javascript, especially server side javascript, such as Node. js programming. Although Promise has its own problems, it still has its unique advantages in solving multi-layer nested callback and other problems.
Common scenarios of Promise are basically on the server side, but in fact it is also useful in the client side, but it is rare at present.
JQuery, as a good client side javascript Library, has fully supported Promise, but the APIS we usually use, such as $. ajax and so on. The features of Promise have been packaged, and developers cannot feel it. However, in some scenarios, Promise must be used for display.
For example, a simple example is to call an external rest api to obtain a task list and generate a select statement on the page.
If you want to use the task list as a separate function and do not want to put the select code generated into the callback called by ajax that retrieves the task list, we usually use "async: false" in ajax calls, so that the task list is synchronized.
function generateTaskSelect(value) {var combine = $('<div></div>');var label = $('<span></span>').text('Task List');var cr = $('<div></div>');var select = $('<select></select>');var names = getTaskNames();names.sort();for (var i=0;i<=names.length-1;i++) {select.append(generateOption(names[i]));}if ((value) && (names.indexOf(value) !== -1)) {select.val(value);} else {if (names.length > 0) {select.val(names[0]);}}combine.append(label).append(cr).append(select);return combine;}function getTaskNames() {var names = new Array();$.ajax({url: $('#serviceUrl').val() + '/tasks',type: "GET",async: false}).done(function(tasks) {tasks.forEach(function(task){names.push(task.name);});}).fail(function(err) {console.error(err);});return names;}function generateOption(option) {if (option) {return $('<option>' + option + '</option>');} else {return $('<option></option>');}}
This solution works well in chrome. Even if ajax calls are synchronized, the page does not feel the lag due to time consumption. However, it does not work in Firefox because the "async: false" attribute is not supported in Firefix, so you must find another solution. At this time, Promise was unveiled. Let's take a look at the code.
function generateTaskSelect(value) {var combine = $('<div></div>');var label = $('<span></span>').text('Task List');var cr = $('<div></div>');var select = $('<select></select>');$.when(getTaskNames()).done(function(taskNames){var names = taskNames;names.sort();for (var i=0;i<=names.length-1;i++) {select.append(generateOption(names[i]));}if ((value) && (names.indexOf(value) !== -1)) {select.val(value);} else {if (names.length > 0) {select.val(names[0]);}}combine.append(label).append(cr).append(select);}).fail(function(err){console(err);});return combine;}function getTaskNames() {var dtd = $.Deferred();$.ajax({url: $('#serviceUrl').val() + '/tasks',type: "GET"}).done(function(tasks) {var names = new Array();tasks.forEach(function(task){names.push(task.name);});dtd.resolve(names);}).fail(function(err) {console.error(err);dtd.reject(err);});return dtd;}function generateOption(option) {if (option) {return $('<option>' + option + '</option>');} else {return $('<option></option>');}}
In the new solution of Promise, the task list is now called asynchronously, and the result of this asynchronous call can be notified to the upper layer of the call chain through Promise, in this way, not only does callback nesting be avoided, but asynchronous calling is maintained to avoid occupying the UI thread and GUI response is ensured.
Among them, the key Promise uses two points:
1. $. Deferred (): This is the Promise object in jQuery. Pay attention to the use of its resolve () and reject () state conversion methods.
2. $. when (): it forms a Promise call chain and decouples nested callback.