How do I defer an ES6 promise like jquery Deferred?

一笑奈何 提交于 2020-05-14 19:49:33

问题


1. Using es6 promise, but the syntax is incorrect.

I'm using es6, and want to make a deferred confirm dialog:

// First, create an empty promise:
let promise = new Promise((resolve, reject) => {})

// Then, show the dialog:
let $dialog = $('#dialog-confirm').show();

// FAIL: I want to trigger the promise resolver, but failed.
$dialog.find('.btn-yes').click(() => { promise.resolve(); })
$dialog.find('.btn-no').click(() => { promise.reject(); })

When I clicked the button, it failed, because the promise does not have the reject and resolve method.

Uncaught TypeError: promise.resolve is not a function(…)

2. jQuery working code:

If using jQuery, we can do the below:

// First, create an empty promise:
var dfd = $.Deferred();
var promise = dfd.promise();

// Then, show the dialog:
var $dialog = $('#dialog-confirm').show();

// SUCCESS: jQuery deferred works
$dialog.find('.btn-yes').click(() => { dfd.resolve(); })
$dialog.find('.btn-no').click(() => { dfd.reject(); })

3. Try to find a deferred interface for es6.

So I searched for an ES6 EDITION of deferred:

https://github.com/seangenabe/es6-deferred

But still I got an error:

undefined:1 Uncaught (in promise) Object {}

In fact, the code is just keep the inner resolve and reject function to outside using closure:

https://github.com/seangenabe/es6-deferred/blob/master/deferred.js

The same strategy if I do:

let dfd = {};

let $dialog = $('#dialog-confirm').show();

let promise = (function() {
    return dfd.promise = new Promise(function(resolve, reject) {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
})();

// FAIL: still not working.
$dialog.find('.btn-yes').click(() => { dfd.resolve(); })
$dialog.find('.btn-no').click(() => { dfd.reject(); })

So, how can I pull out the resolve and reject action out of my promise creation call?


回答1:


var Deferred = require('es6-deferred');
var d = new Deferred(
     (resolve, reject) => {
         // Process your Async or sync process here and
         // call resolve() and pass your data as argument when
         // it is successful
         // same shit for error case just call reject() instead.
     }
);

d.then(
    (res) => {
    // res is your data passed into the resolve method the deferred promise
    // Handle your click here
    }, (err) => {
    // err is your data or error passed into the reject method
    // Handle your click here
  }
);



回答2:


For those of you getting here from Google its worth mentioning that ES6 promises are good and I use them a lot. However, there are use cases where the deferred pattern results in significantly less code. In most cases you should likely just use the ES6 promises but in those special cases where the deferred pattern makes sense then its easy enough to wrap an ES6 promise. Including a node module seems like over kill in my mind.

function generateDeferredPromise() {
  return (() => {
    let resolve;
    let reject;

    let p = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });

    return {
      promise: p,
      reject,
      resolve
    };
  })();
}



回答3:


Move jquery statements inside the promise

let promise = new Promise((resolve, reject) => {
 let $dialog = $('#dialog-confirm').show();
$dialog.find('.btn-yes').click(() => { resolve(); })
$dialog.find('.btn-no').click(() => { reject(); })

})



回答4:


If you have Promise polyfill, just use Promise.resolve();

In your example:

// Show the dialog:
let $dialog = $('#dialog-confirm').show();

$dialog.find('.btn-yes').click(() => { Promise.resolve(); })
$dialog.find('.btn-no').click(() => { Promise.reject(); })



回答5:


Finally found out the point:

In fact the deferred action and es6-deferred package is well done, and works perfectly.

import Deferred from 'es6-deferred';

const confirm = function(msg='confirm?') {
    const dfd = Deferred();
    const $dialog = $('#dialog-confirm').show()
    $dialog.find('.msg').text(msg);
    $dialog.find('.btn-yes').click(() => { dfd.resolve(); })
    $dialog.find('.btn-no').click(() => { dfd.reject(); })
    return dfd;
};

// ....    

The actual problem is I got the bellow error:

undefined:1 Uncaught (in promise) Object {}

The real reason is that I called:

// Another place
confirm('Do you like to delete this item?').then(function() {
    // Do the deletion.
});

Then I click the .btn-no to cancel, at this time, the dfd.reject() is triggered, but at the same time, the promise do not have any catch method to process the reject action yet.

So caused this problem.

When I added the missed reject function to the call, everything goes well.

Conclusion:

If an ES6 promise was REJECTED with no CATCH phrase registered, it causes problem!



来源:https://stackoverflow.com/questions/38418256/how-do-i-defer-an-es6-promise-like-jquery-deferred

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!