Learn from the similarities and differences between ES6 Promise and JQuery Deferred Promise

Source: Internet
Author: User

Deferred and Promise

ES6 and JQuery have deffered and Promise, but they are slightly different. But their role can be easily described in two words.

    • Deffered Trigger Resolve or Reject
    • What to do after resolve or reject is declared in Promise (callback)

In JQuery

var deferred = $.Deferred();var promise = deferred.promise();

In the ES6

var deferred = Promise.defer();var promise= defered.promise;

The MDN declares that Deferred was declared expired in Gecko 30 and should not be used, but instead new Promise() . About new Promise() will be explained later.

The deferred/promise of JQuery

The most commonly used Promise objects in JQuery are $.ajax() returned, and the most common methods are not then , but done , fail and always . Besides $.ajax() , JQuery also provides $.get() , $.post() and $.getJSON() so simplify Ajax calls, which return the $.ajax() same return value as a Promise object.

$.ajax()a Jqxhr object is actually returned. But JQXHR implements the Promise interface of JQuery, so it is also a Promise object.

done()fail()And always()

done()Adds a callback deferred.resolve() that fail() adds deferred.reject() a callback. So when the Ajax call succeeds done() , the added callback is executed, and the callback is executed when the call fails fail() . However, the added callback will be executed regardless of success or not always() .

Here done() , fail() and always() both add callbacks in a similar way, which means that done() fail() always() several callbacks that they add will execute sequentially, regardless of the number of times they are executed.

In general, Ajax is performed like this

// 禁用按钮以避免重复提交$("#theButton").prop({    disabled: true});// 调用 Ajax 提交数据,假设返回的是 JSON 数据var jqxhr = $.ajax("do/example", {    type: "post",    dataType: "json",    data: getFormData()});jqxhr.done(function(jsonObject) {    // Ajax 调用成功    console.log("success with data", jsonObject);}).fail(function() {    // Ajax 调用失败    console.log("failed")}).always(function() {    // 不管成功与否,都会执行,取消按钮的禁用状态    $("#theButton").prop({        disabled: false    });});

The above is the most common use of the most common, but in a project is always so written Ajax, a little tired, a little agreement to wrap it up will be more convenient to use. First, let's say we define the JSON that is returned in this format:

{    "code": "int, 0 表示成功,其它值表示出错",    "message": "string, 附加的消息,可选",    "data": "object,附加的数据,可选}

Then app define a method for the project's public class ajax

app.ajax = function(button, url, data) {    if (button) {        button.prop("disabled", true);    }    return $.ajax(url, {        type: "post",        dataType: "json",        data: data    }).done(function(json) [        if (json.code !== 0) {            showError(json.message || "操作发生错误");        }    }).fail(function() {        showError("服务器错误,请稍后再试");    }).always(function() {        if (button) {            button.prop("disabled", false);        }    });};// 调用app.ajax("do/example", getFormData()).done(function(json) {    if (json.code === 0) {        // 只需要处理正确的情况啦    }});

However, it is still a bit uncomfortable, if you do not need to judge json.code === 0 the better. This one...... You can use a Deferred to handle it yourself:

app.ajax = function(button, url, data) {    if (button) {        button.prop("disabled", true);    }    var deferred = $.Deferred();    $.ajax(url, {        type: "post",        dataType: "json",        data: data    }).done(function(json) [        if (json.code !== 0) {            showError(json.message || "操作发生错误");            deferred.reject();        } else {            deferred.resolve(json);        }    }).fail(function() {        showError("服务器错误,请稍后再试");        deferred.reject();    }).always(function() {        if (button) {            button.prop("disabled", false);        }    });    return deferred.promise();};// 调用app.ajax("do/example", getFormData()).done(function(json) {    // json.code === 0 总是成立    // 正常处理 json.data 就好});

Note that this is not the result of a direct return $.ajax() JQXHR object, it returns the Deferred object of the new object promise .

Review Ajax, now need to cut to the chase, find JQuery Promise and ES6 Promise close to the place- then() .

Jquery deferred.then()

Before jquery 1.8 (excluding 1.8, such as jquery 1.7.2), it deferred.then() was a syntactic sugar that was put done() and fail() put together. JQuery modified the behavior in the 1.8 version to deferred.then() make then() the behavior similar to the Promise then() . From the JQuery documentation you can see the 1.8 version change-kill callback and replace with filter:

// version added: 1.5, removed: 1.8deferred.then( doneCallbacks, failCallbacks )// version added: 1.7, removed: 1.8deferred.then( doneCallbacks, failCallbacks [, progressCallbacks ] )// version added: 1.8deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

Callback can be simply treated as an event, the value is generally not changed after the callback, and the filter is different, a value passed in the filter and returned from the filter, may have changed. Let's give an example to illustrate

var deferred = $.Deferred();var promise = deferred.promise();promise.then(function(v) {    console.log(`then with ${v}`);}).done(function(v) {    console.log(`done with ${v}`);});deferred.resolve("resolveData");

Results in the JQuery 1.7.2

then with resolveDatadone with resolveData

Results in the JQuery 1.8.0

then with resolveDatadone with undefined

From the above, the deferred.then() semantic and ES6 semantics of JQuery are Promise.then() basically consistent. app.ajax then() It will help to understand the ES6 Promise if the above conversion is realized.

app.ajax = function(button, url, data) {    if (button) {        button.prop("disabled", true);    }    return $.ajax(url, {        type: "post",        dataType: "json",        data: data    }).then(function(json) {        if (json.code !== 0) {            showError(json.message || "操作发生错误");            return $.Deferred().reject().promise();        } else {            return $.Deferred().resolve(json).promise();        }    }, function() {        showError("服务器错误,请稍后再试");        deferred.reject();    }).always(function() {        if (button) {            button.prop("disabled", false);        }    });};// 调用方式没变,用 done,也可以用 thenapp.ajax("do/example", getFormData()).done(function(json) {    // json.code === 0 总是成立    // 正常处理 json.data 就好});
From JQuery Promise to ES6 Promise

The code above is too long to refine the key parts (motioned, not run)

var promise = $.ajax();promise.then(function(data) {    // resolve    return data.code        ? new Promise().reject()        : new Promise().resolve(data);    // 如果没有错,就返回一个新的 promise,并使用 data 来 resolve,    // 也可以直接返回 data,    // 这样后面 then 的 resolve 部分才能收到数据}, function() {    // rejected});// 调用阶段promise.then(function(data) {    // 处理 data});

Perhaps you have not noticed, in fact the above code is basically the ES6 Promise. The following formally rewrite the above schematic code with ES6 Promise

var promise = new Promise(function(resolve, reject) {    $.ajax().then(resolve, reject);    // 上面这句没看懂?那换成这样你一定会懂    // $.ajax().then(function(data) {    //     resolve(data);    // }, function() {    //     reject();    // });}).then(function(data) {    return data.code        ? Promise.reject()        : Promise.resolve(data);    // 这里 Promise.resolve(data) 同样可以直接替换为 data});// 调用没变promise.then(function(data) {    // 处理 data});

What's the difference? Unconsciously will be ES6 Promise!

ES6 's Promise

The above has brought out the ES6 Promise, now only need to list the common methods as a reference can be

Note that the lowercase promise representation of the Promise object

    • new Promise(executor), a new Promise object is generated

      executor(resolve, reject)
      executor, resolve and reject both are functions, in executor which the return data is handled correctly, and resolve() exception handling is returned directly or to the throw new Error(...) reject() data.

    • Promise.resolve(data), the Promise object is generated andresolve

    • Promise.reject(), the Promise object is generated andreject
    • promise.then(onResolve, onReject)And then...... Continue processing

    • promise.catch(onReject), project.then(null, onReject) the syntax of sugar, and JQuery is promise.fail() similar (but different).
Reference
    • ECMAScript Language specification-ecma-262 6th Edition
    • Deferred-mozilla | MDN
    • Promise-mozilla | MDN
    • Deferred Object | JQuery Documentation

Learn from the similarities and differences between ES6 Promise and JQuery Deferred Promise

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.