8

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?

Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
  • What is purpose of using `Promise`? `.then()` does not appear at Question? – guest271314 Jul 17 '16 at 05:51
  • 1
    This question has been asked many times. A deferred object was not built into ES6 promises because it simply isn't needed as explained [here](http://stackoverflow.com/questions/32853105/when-would-someone-need-to-create-a-deferred/32857145#32857145). And, if you want to manufacture one, it takes only a few lines of ES6 code to do so. – jfriend00 Jul 17 '16 at 05:51
  • In fact, I'm using vuex, I create the promise to pop out the dialog in the vuex actions, but I need to resolve or reject the promise in the component. – Alfred Huang Jul 17 '16 at 05:51
  • `Promise` is resolved or rejected at `javascript` at Question, though no value or reason passed as parameter? – guest271314 Jul 17 '16 at 05:52
  • @guest271314 `promise.then(function() { $dialog.hide(); })` – Alfred Huang Jul 17 '16 at 05:52
  • @fish_ball At `click` which element? – guest271314 Jul 17 '16 at 05:54
  • @guest271314 the dialog has two buttons: `.btn-yes` and `.btn-no` – Alfred Huang Jul 17 '16 at 05:55
  • No value is passed to `resolve` or `reject` ? – guest271314 Jul 17 '16 at 05:56
  • 2
    How to create a deferred in a few lines of ES6 promise code: http://stackoverflow.com/questions/37651780/why-does-the-promise-constructor-need-an-executor/37673534#37673534 (though you should NEVER need to do so). – jfriend00 Jul 17 '16 at 05:58
  • What is purpose of using `.click()` where `Promise` would be resolved or rejected once? You could utilize `$.fn.one()` to achieve same result? Not certain why you cannot use `jQuery.Deferred()` if you are using other jQuery functions? Can you create a stacksnippets or jsfiddle to demonstrate issue? – guest271314 Jul 17 '16 at 06:20
  • Why are you using a Promise to control the visibility of a dialog anyway? What's wrong with using regular event handlers? – Mulan Jul 17 '16 at 15:14

3 Answers3

29

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() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    [resolve, reject] = [res, rej];
  });
  return {promise, reject, resolve};
}
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
aashtonk
  • 789
  • 7
  • 15
1

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(); })

})
Piyush.kapoor
  • 6,715
  • 1
  • 21
  • 21
  • I use vue framework so the triggering point is separated into different code files. – Alfred Huang Jul 17 '16 at 05:44
  • I return the dfd or promise object outside, and trigger the resolve action in other script file. – Alfred Huang Jul 17 '16 at 05:45
  • you can pass the entire function to the promise from the another file let promise = new Promise(yourfunction_imported) – Piyush.kapoor Jul 17 '16 at 05:47
  • That breaks my design. So I asked for a solution. – Alfred Huang Jul 17 '16 at 05:48
  • 1
    @fish_ball Why is the code where you attach the dialog's events in a different file from where you are creating the promise? Please explain that clearly in your question (preferably using code examples). So far you have only asked us how to make a specific implementation when you should be asking how to solve your problem. – JLRishe Jul 17 '16 at 06:12
0
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 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
  }
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Disfigure
  • 720
  • 6
  • 19
  • 7
    Using a node module for 10 lines of code? Reminds me to this: http://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/ (whoever used this module deserved the broke of their projects, it is a very easily implementable utility function, like this). – cstuncsik Jul 17 '16 at 07:38
  • 1
    @Disfigure - I think the point is that creating a deferred from an ES6 promise is only 8 lines of code as seen here: http://stackoverflow.com/questions/37651780/why-does-the-promise-constructor-need-an-executor/37673534#37673534 – jfriend00 Jul 17 '16 at 07:51
  • 1
    My example does not use that module - it was originally written code. It is similar code because that's just how you do it. – jfriend00 Jul 17 '16 at 16:28
  • 1
    Does not answer the question as it is not a native es6 promise solution. – Ivar Nov 27 '19 at 16:37