http-client
http-client copied to clipboard
Canceling requests with TypeScript
Since the cancel/abort
function is added runtime to the Promise<HttpResponseMessage>
returned by .send()
in http-client.js
, the TypeScript compiler doesn't know about its existence.
I have a PR ready for this... except the build chain won't support it properly.
We need generics support to declare interface CancellablePromise<T> extends Promise<T>
.
This is one of the latest change in babel-dts-generator
but of course we can't use it because aurelia-http-client
still uses Babel 5.8 but babel-dts-generator
master is on 6.0 now.
We hope to move to 6.x soon. We've been contributing to the dts generator a lot trying to get it updating to the new Babel version. I think we're really close. @cmichaelgraham can you comment on that?
@jods4 babel-dts-generator has been updated to support generics. as part of this, it also has been updated to the new babel6 plugin architecture.
the first aurelia repo to test against is metadata - a problem has been identified where class member's code comments were not being successfully included in the generated .d.ts
file.
failing tests were created and the issues resolved, but during the code review, a refactoring was requested (a good suggestion).
i will try to get this added to the PR so we can proceed.
@cmichaelgraham It looks like this is still a bug in the d.ts generator. Can you address it?
i'll have a look :smile:
@cmichaelgraham Was this ever addressed?
need to test with the latest... will do that tonight... (i think we should be ok with the required generics)
@heruan - can you submit the PR so i can test with the latest babel-dts-generator?
ping @EisenbergEffect
@jods4 had a PR ready, let's hear from him!
thanks @heruan :smile: @jods4 - can you submit a PR?
Hey guys, sorry that's so old now I'm really not sure where I made this anymore :D
BTW instead of inheritance, since then we got intersection types, so an alternative could be to type the function as Promise<T> & { abort(): void }
To piggyback on @jods4's comment, you can solve this problem in your own codebase by just declaring the following type:
type CancellablePromise<T> = Promise<T> & { cancel(): void }
I think this should be added more formally to the http-client
type definitions though.
BTW, maybe that's worth opening another issue but whatwg has finally decided what is the standard way to abort a fetch. They said adding abort
on Promise
is not working well as soon as you chain them, so they opted for a different design based on a fetch controller. Maybe it's worth revising the design of http-client
as well (of course abort
could be left on the returned promise for back compat, but maybe not exposed in the .d.ts
).
@jods4 do you have the link to the supporting documentation from whatwg? Would be useful going forward in this discussion, thanks.
@michaelbull whatwg discussions and specs are dry as hell.
Have a look at this introductory article from Google: https://developers.google.com/web/updates/2017/09/abortable-fetch
Or look at the docs in MDN: https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
This has landed in all 3 major browsers.
I first patched .d.ts type with addition Promise<T> & { abort(): void }
Second, I replace native promise with bluebird promise : http://bluebirdjs.com/docs/getting-started.html
Thrid I add a small wrapper on httpclient send() method return promise ::
I follow the bluebird doc : http://bluebirdjs.com/docs/api/cancellation.html#cancellation :
function makeCancellableHttpClientPromise(httpClientPromise) {
return new Promise(function(resolve, reject, onCancel) {
// Note the onCancel argument only exists if cancellation has been enabled!
onCancel(function() {
//use abort to avoid confusion with bluebird cancel() method
httpClientPromise.abort();
});
httpClientPromise.then(resolve, reject);
});
}
It works fine !
@BBosman maybe you could take a look at this one? and the one linked?
Had a quick look, but I'm running into limitations of the current babel-dts-generator
based toolchain.
Attempt 1:
export type CancellablePromise1<T> = Promise<T> & {
cancel: () => void;
abort: () => void;
};
Results in TypeAlias not supported
warnings during build and the .d.ts
file being truncated from that point.
Attempt 2:
interface CancellablePromise<T> extends Promise<T> {
cancel: () => void;
abort: () => void;
}
Results in the build crashing with an node.toCode is not a function
error. It's choking on the extends
.
Attempt 3:
interface Cancellable<T> {
cancel: () => void;
abort: () => void;
}
And then using Cancellable&Promise<HttpResponseMessage>
as a return type results in a crashed built with an Unsupported type annotation type: IntersectionTypeAnnotation
error.
So before we/I can fix this I think we need some enhancements in babel-dts-generator
to make this scenario possible within our current toolchain. I'm open to suggestions or alternatives though.
@BBosman alternative could be to migrate this one to TS? but that can be too much of a task for a working thing