Some things that are "better" with this BetterPromise
implementation:
-
BetterPromise # then(..)
accepts aBetterPromise
(orPromise
) instance passed directly, instead of requiring a function to return it, so that the promise is linked into the chain.var p = BetterPromise.resolve(42); var q = Promise.resolve(10); p.then(console.log).then(q).then(console.log); // 42 // 10
-
BetterPromise # unthen(..)
/BetterPromise # uncatch(..)
/BetterPromise # unfinally(..)
allows you to unregister a fulfillment or rejection handler that you previously registered on a promise viathen(..)
orcatch(..)
, or unregister a resolution handler that you previously registered on a promise viafinally(..)
.NOTE: This seems to be the majority use-case for why many like/want "promise cancelation" -- IOW, often what you want is to just stop observing a promise's resolution, not actually forcibly cancel the operation is comes from.
var p = new BetterPromise(function(res){ setTimeout(function(){ res(42); },100); }); function f1(v) { console.log(`f1: ${v}`); } function f2(v) { console.log(`f2: ${v}`); } function f3() { console.log("finally!"); } p.then(f1); p.then(f2); p.finally(f3); p.unthen(f1); p.unfinally(f3); // later // f2: 42
-
BetterPromise # finally(..)
is included (assumed implemented since it's already stage-4). Registers a resolution handler which is called on either fulfillment or rejection, sorta like if you didthen( fn, fn )
(but not exactly).var p = BetterPromise.resolve(42); p .finally(function(){ console.log("resolved!"); }) .then(function(v){ console.log(`still: ${v}`); }); // resolved! // still: 42
-
BetterPromise # thenLog()
/BetterPromise # catchLog()
inserts a step in a promise chain that simply prints the value to the console (console.log
for fulfillment,console.error
for rejection) and passes the value or rejection along to the next step untouched.var p = BetterPromise.resolve(42); p .thenLog() .then(function(v){ console.log(`still: ${v}`); }); // 42 // still: 42
-
Instead of silently being swallowed, if a synchronous exception is thrown in a
BetterPromise
constructor after the promise has already been synchronously resolved (fulfillment or rejection), that exception overrides and causes the promise to be rejected with that exception.var p = new BetterPromise(function(res){ res(42); throw 10; }); p.then( function(v){ console.log(`then: ${v}`); }, function(e){ console.log(`oops: ${e}`); } ); // oops: 10
-
BetterPromise.try(..)
(static helper) is implemented (so not just draft). Runs a function (with no arguments) synchronously, returns a promise for its return value (or adopts its promise), catches any synchronous exception and turns it into a rejection.var p = BetterPromise.try(function(){ undefined(42); }); p.catch(console.log); // TypeError: undefined is not a function
-
BetterPromise.deferred(..)
(static helper) constructs an instance of the promise, but also extracts itsresolve(..)
andreject(..)
capabilities, and returns all 3 in an object (aka, a "deferred").var { pr, resolve, reject } = BetterPromise.deferred(); pr.then(console.log); resolve(42); // 42
-
BetterPromise.lift(..)
(static helper) lifts an error-first, callback-last style function to beBetterPromise
returning instead.var readFile = BetterPromise.lift(fs.readFile); readFile("/path/to/file.txt") .then(printContents);
-
BetterPromise.control(..)
(static helper) wraps a function so that when called, it first creates anAbortController
instance, passes in itssignal
as the first argument to the original function, and returns a controller object that has both apr
for the function's completion, as well as acancel(..)
to send the abort signal. Ostensibly, the original function can then observe/respond to that passed-in signal and do something appropriate with it, like canceling its own behavior, passing it tofetch(..)
to abort an Ajax call, etc.async function main(signal,url) { signal.addEventListener("abort", .. ); // .. var resp = await fetch(url, { signal }); // .. } var fn = BetterPromise.control(main); var { pr, cancel } = fn("http://some.url"); pr.then(..); // later cancel(); // sends cancelation signal into `fn(..)`
@atymchuk I use
var
for variable declarations at the top level of a function, andlet
for variable declarations inside of blocks. IMO,var
signals "will be used across the whole function" whilelet
signals "will be used only in this limited scope of this block". Both signals are important, but usinglet
for both degrades that signal difference.