6

Refer to Rookie mistake #4: using "deferred" in Nolan Lawson's article: We have a problem with promises (btw a great post!), I try not to use deferred style promises anymore. Recently I've encountered a practical example that I can't figure out how to NOT code this in deferred way, so I need some advices.

Here is the example, an angular factory:

function ConfirmModal($q, $modal) {
    return {
        showModal: function _showModal(options) {
            var _modal = $modal(options)
            var deferred = $q.defer()

            _modalScope.confirm = function(result) {
                deferred.resolve(result)
                _modal.hide()
            }

            _modalScope.cancel = function(reason) {
                deferred.reject(reason)
                _modal.hide()
            }

            return deferred.promise
        }
    }
}

I hide some unrelated details(eg. implementation of _modalScope), the core idea is: $modal provide a ui widget which contains two button: Confirm and Cancel. When Confirm is been clicked, call _modalScope.confirm and resolve the deferred promise, otherwise reject the deferred promise by calling _modalScope.cancel when Cancel is been clicked.

I tried to rewrite by using return $q(function(resolve, reject) { ... }), but I really don't know how/when to call resolve and reject in this constructor, because the real logic is in the _modalScope.confirm/cancel method. I'm struggled with this problem for days, really hope someone can help me.

Thanks!

nightire
  • 1,371
  • 2
  • 11
  • 21
  • 1
    In fact, you are not using the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572) here, because `$modal` is not a promise api already. Deferreds are totally fine for promisifying things! – Bergi Jun 27 '15 at 16:19
  • @Bergi oh, fairly point, I didn't realize that, thanks! – nightire Jun 27 '15 at 16:22

1 Answers1

5

Presuming the code in your questions is functional and _modalScope is accessible from the _showModal() function, then the code below should answer your question:

function ConfirmModal($q, $modal) {
    return {
        showModal: function _showModal(options) {
            return $q(function(resolve, reject) {
                var _modal = $modal(options)

                _modalScope.confirm = function(result) {
                    resolve(result)
                    _modal.hide()
                }

                _modalScope.cancel = function(reason) {
                    reject(reason)
                    _modal.hide()
                }
            });
        }
    }
}
JME
  • 3,592
  • 17
  • 24
  • I've tried this before and I thought it not works, and I tried it again after read your answer, it actually works! I thought it not works because angular throws an error, but I didn't read it carefully, turns out the error is not related to this modification, my bad. Thank you very much. – nightire Jun 27 '15 at 16:19
  • Won't work with Angular 1.2. Unsure about Angular 1.3. Seems to work with Angular 1.4 and 1.5. – Harry Pehkonen Apr 19 '16 at 21:23