Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any downside to exposing resolve() and reject() outside of the Promise constructor? [duplicate]

I created this little helper to expose resolve and reject outside of the Promise's constructor

export function createPromise() {
    let resolve,reject;
    let promise = new Promise((r,j) => {
        resolve = r;
        reject = j;
    });
    Object.assign(promise,{resolve,reject});
    return promise;
}

Because sometimes it's just really awkward to wrap your entire script in

new Promise((resolve,reject) => { 
   // hundreds of lines of code, most which have nothing 
   // to do with this Promise but I need the Promise object 
   // at the top level somewhere so that I can expose it, 
   // but it won't be resolved until some deeply nested construct is hit  
})

Or to give a more concrete example:

let p1 = kb.createPromise();
let p2 = kb.createPromise();

Promise.all([p1,p2]).then(() => {
    $('#calendar-bookings').scrollIntoView({
        duration: 200,
        direction: 'y'
    });
});

$('#bookings-table')
    .dataTable(getOptions(dtSourceUrl, {date, driverOptions}))
    .one('draw.dt', () => p1.resolve());

ReactDOM.render(<VehicleTimeline start={dateMom.toDate()} onLoad={() => p2.resolve()}/>, document.getElementById('vehicle-timeline'));

This way I also don't have to worry about whether resolve() is called synchronously before I even get a chance to bind my .then. [I stand corrected, the .then will fire immediately] I think this is pretty clear: create two promises, bind the .then, and only after is it even conceivable that they're resolved.

Sure, this would allow anyone who you've passed your Promise off to to resolve it (i.e. giving control away from the Promise creator and to the consumer) but if the consumer fires it early, that's their loss because presumably they're the ones interested in the event, no?

Also, this would give the consumer the ability to reject() the Promise which they could abuse as a sort of Promise cancellation. I'm not saying that's a good idea, but I don't think the extra freedom is necessarily bad either.

Is there anything else I'm missing? Any problems with my createPromise method?

like image 426
mpen Avatar asked Nov 08 '22 15:11

mpen


1 Answers

This is a variation of the deferred pattern except that you return the promise object with the resolve/reject functions in the promise object. The original deferred pattern created an object with the promise and the resolve/reject functions separately. So you can pass out the promise without exposing the controls.

To be honest, there are very little places where actually breaking out of the constructor scope is needed. In my opinion it's a little bit easier to make a mistake with this pattern and end up with unresolved promises than with the constructor pattern. As far as I can tell really, the only benefit from the constructor pattern over the deferred pattern that you get is that you can throw and reject the promise immediately (through a sync mistake).

like image 153
MinusFour Avatar answered Nov 14 '22 21:11

MinusFour