Promise Handle

An experimental imperative pattern for creating and resolving promises inside an async JavaScript function.

Experiment

When using the new async/await syntax in JavaScript, it is awkward to create and return a Promise, other than the default. We’re avoiding the use of callbacks with async/await but in corner cases where you need to create and resolve/reject a separate promise, it is awkward.

Let’s create a definition for a new type of object that provides an
imperative interface for a Promise, without the need for defining a callback.

We will call this new object a PromiseHandle. An instance of this object will contain the following members:

1
2
3
4
5
{
promise, // A field containing an instance of a Promise
reject, // A method for rejecting the Promise instance
resolve, // A method for resolving the Promise instance
}

A PromiseHandle is like new Promise((resolve, reject)=>{}), except you have a handle to call resolve and reject outside the function.

Next, let’s create a factory function that returns an instance of PromiseHandle.

An example implementation of this factory function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function newPromiseHandle () {
const handle = {};
handle.promise = new Promise((resolve, reject) => {
handle.resolve = value => {
resolve(value);
return handle.promise;
};
handle.reject = value => {
reject(value);
return handle.promise;
};
});
return handle;
}

In this example, the resolve and reject methods will return instances of the promise instance as a convenience.

Here is an example of basic usage:

1
2
3
4
5
6
7
8
9
10
const handle = newPromiseHandle();
// Access the promise
let pending = handle.promise;
// Reject the promise
handle.reject('rejected');
// Resolve the promise
handle.resolve('resolved');

Here is a more in depth example, showing how to return a single value obtained asynchronously despite multiple calls to the same method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let pending = null;
async function example() {
if (pending) return pending;
const handle = newPromiseHandle();
pending = handle.promise;
try {
await Promise.resolve('example');
handle.resolve('resolved');
} catch (e) {
handle.reject('rejected');
}
pending = null;
return handle.promise;
}

Conclusion

It is important to keep in mind that an async function always returns a new instance of a promise. In the last example, we are creating a new Promise instance with every example() call. Each new Promise instance wraps the single Promise instance associated with our Promise handle. It would be more efficient in this particular case to not use an async function.

This pattern does eliminate the use of a callbacks when creating a promise inside an async function.

The PromiseHandle factory described above is included in catchify.

Create Authorization Basic Header

The HTTP Authorization request header is sometimes required to authenticate a user agent with a server.
This post explains how to create the header on linux at command line.

Syntax

The HTTP Authorization request header has the following syntax:

1
Authorization: <type> <credentials>

The type is typically “Basic”, in which case the credentials are of the form user:password encoded as base64.

Curl will generate this header for us if we use the -u option:

1
2
3
4
$ curl -v -u user:password majgis.github.io
...
> Authorization: Basic dXNlcjpwYXNzd29yZA==
...

Now for the real question, how do we generate this header for use with curl’s -H option?

Experiments

Here is the first attempt to base64 encode user:password that is WRONG:

1
2
3
# This is WRONG!
$ echo user:password | base64
dXNlcjpwYXNzd29yZAo=

Notice that dXNlcjpwYXNzd29yZAo= does not equal dXNlcjpwYXNzd29yZA==.

Let’s decode to find the difference:

1
2
3
4
5
$ echo dXNlcjpwYXNzd29yZAo= | base64 -d
user:password
$ echo dXNlcjpwYXNzd29yZA== | base64 -d
user:password%

That % is different. What is that?

The % symbol is how zsh handles the end of partial lines.
In other words, zsh assumes we want our prompt on a newline even if the last command didn’t end with
a newline. That % symbol is how we know the difference between a newline the last command output
and a newline zsh graciously inserted for us.

Let’s execute this command under bash and see the difference:

1
2
3
4
5
6
bash
$ echo dXNlcjpwYXNzd29yZAo= | base64 -d
user:password
$ echo dXNlcjpwYXNzd29yZA== | base64 -d
user:password$

The base64 encoded user:password that curl generated is not terminated with a newline, unlike the one we generated.

Let’s see if we can get echo to not add that newline.

1
2
$ man echo | cat | grep 'newline'
-n do not output the trailing newline

The -n option for echo is what we want.

1
2
$ echo -n user:password | base64
dXNlcjpwYXNzd29yZA==

We see that the output is exactly the same as what curl generated.

Putting it all together:

1
2
3
4
$ curl -v -H "Authorization: Basic `echo -n user:password | base64`" majgis.github.io
...
> Authorization: Basic dXNlcjpwYXNzd29yZA==
...

Take Away

In zsh, a % symbol is placed at the end of a line where zsh inserted a newline for us.

It is important to include echo’s -n option when piping content to an encoder to avoid a
newline character being included in the encoded output.

1
$ echo -n user:password | base64

Experimental Setup

1
2
3
4
5
6
7
8
9
10
11
$ echo && curl --version && echo && lsb_release -d -c && echo && echo $0 && zsh --version
curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2g zlib/1.2.11 libidn2/0.16 libpsl/0.17.0 (+libidn2/0.16) librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets HTTPS-proxy PSL
Description: Ubuntu 17.04
Codename: zesty
/usr/bin/zsh
zsh 5.2 (x86_64-ubuntu-linux-gnu)

References

JS Async Always Returns New Promise

A JavaScript async function always returns a new promise, even if you immediately return a promise.

Experimental Setup

1
2
3
4
5
6
7
8
9
$ node -v
v8.4.0
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial

Experiments

Confirm that a new promise is always generated by an async function

1
2
3
4
5
6
7
// test1.js
const promise = new Promise((resolve,reject)=>resolve());
async function test(){
return promise;
}
console.log(test() !== test());
1
2
$ node test1.js
true

Examine the behavior of the resolve function passed to executor function of a new promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// test2.js
const resolvedPromise = new Promise(resolve => resolve('resolved'));
const rejectedPromise = new Promise((_, reject) => reject('rejected'));
function test2(promise){
return new Promise(resolve => {
resolve(promise);
});
}
test2(resolvedPromise).then(v => {
console.log('resolvedPromise:', v);
});
test2(rejectedPromise).catch(v => {
console.log('rejectedPromise:', v);
});
1
2
3
$ node test2.js
resolvedPromise: resolved
rejectedPromise: rejected

Take Away

Working with an async function is equivalent to working within the executor of a new promise.

The resolve function, the first argument of the promise executor, behaves the same as the return statement of an async
function.

1
2
3
4
5
6
function test() {
return new Promise((resolve,reject) => {
// resolve === return
// reject === throw
}
}

References