Reputation: 437
I'm currently writing an e2e test and I would like to create some classes which abstract certain async tasks for me. In the end I would like to instantiate an object, which let's me chain async functions. Let's say I have a Walker
which let's me navigate through the page. I would like to use it in this way:
const walker = new Walker(t)
await walker
.goToMainPage()
.goToProfile()
Currently I can only use it like this:
const walker = new Walker(t)
await walker.goToMainPage()
await walker.goToProfile()
This is a rough implementation of how I currently implemented my Walker Class. Where t
is and object which allows me to do asynchronous actions within my browser.
class Walker {
constructor(t) {
this.t = t;
}
async goToMainPage () {
await t.goTo('url/main')
return this
}
async goToProfile () {
await t.goTo('url/Profile')
return this
}
}
Any ideas on how to create async chainable function calls?
Upvotes: 4
Views: 1412
Reputation: 138437
await
does not only work on Promises, but on every object that provides a .then
handler ... therefore your Walker could implement a .then
method to allow awaiting:
class Walker {
constructor(t) {
this.t = t;
// set up a task queue for chaining
this.task = Promise.resolve();
}
// shedules a callback into the task queue
doTask(cb) {
// TODO: error handling
return this.task = this.task.then(cb);
}
// allows to use this like a promise, e.g. "await walker";
then(cb) { cb(this.task); }
goToMainPage () {
this.doTask(async () => { // shedule to chain
await t.goTo('url/main')
});
return this; // return walker for chaining
}
}
That allows you to do:
await walker.goToMainPage();
await walker.goToMainPage().goToMainPage();
If you return something from inside doTask
, await
ing it will resolve to that:
returnStuff() {
this.doTask(() => "stuff");
return this;
}
//...
console.log(await walker.returnStuff()); // "stuff"
console.log(await walker.returnStuff().goToMainPage()); // undefined, result gets lost
Upvotes: 7
Reputation: 44125
You're using async/await
- it's essentially a replacement for Promise chaining (and Promises are themselves a solve for callback hell). If you really wanted to use chaining:
walker().then(w => w.goToMainPage()).then(w => w.goToProfile());
Upvotes: 2