javascriptember.jspromisersvp-promise

How do I understand this custom use of Promise in code


I use some Promise code used in my application as below;

import { Promise, resolve, all } from 'rsvp';


someAction: function(secId, fld, callback) {
    var self = this;
    var section = self.findSection(self.get('allSecs'), secId);
    var myPendingPromise = section.myPendingPromise || resolve();
    myPendingPromise = myPendingPromise.then(function(){
        return self.myCustomPromise(secId, fld, callback);
    });
    set(section, 'myPendingPromise', myPendingPromise);
},


myCustomPromise: function(secId, fld, callback){
    var self = this;
    return new Promise(function(resolve, reject){
        var deferred = self.myCustomRule(someFlds); //Makes an API call
        deferred.then(function(response) {
            resolve(response);
        }, function(){
            resolve(true);
        });
    });
},

Now, I am a bit confused why the following lines are added specifically;

var myPendingPromise = section.myPendingPromise || resolve();
myPendingPromise = myPendingPromise.then(function(){
    return self.myCustomPromise(secId, fld, callback);
});
set(section, 'myPendingPromise', myPendingPromise); 

Also, I did not find "myPendingPromise" used anywhere else apart from this function. Is there some pattern which I need to be aware of to be able to understand this code? It would be great to understand just the usage of these 3 lines of code above.


Solution

  • What is that

    It looks like an attempt to solve concurrency problem by adding all new promises to promise chain (queue). I prepared a simplified example based on your code that demonstrates how it works.

    What exactly each line does:

    //Extract pending promise from section object. If undefined, use resolve() 
    //to create and resolve dummy promise:
    var myPendingPromise = section.myPendingPromise || resolve();
    
    //Add new promise to chain, so it would start after 
    //pending promise is resolved:
    myPendingPromise = myPendingPromise.then(function(){
        return self.myCustomPromise(secId, fld, callback);
    });
    
    //Save new promise chain into section object:
    set(section, 'myPendingPromise', myPendingPromise); 
    

    Why it's a bad solution to concurrency problem (my opinion)

    1. A bit hard to read and understand
    2. If promise takes a long time to finish and someAction is called many times, queue can grow uncontrollably long
    3. It seems that nothing indicates to user that something is running

    What is a good solution (again, my opinion)

    1. Use library like ember-concurrency to manage concurrency
    2. Avoid using queue strategy for concurrency problems. If you need to use "queue" strategy, take measures to limit queue length
    3. Add some indication so user sees that button worked and request is happening. It's easy to do using ember-concurrency