Consider following case:
var Calc = function () {
// proprties
this.value = 0
// handler's
this.Add = (__value) => { this.value = this.value + __value; return this }
this.Subtract = (__value) => { this.value = this.value - __value; return this }
}
var = (new Calc()).Add(2).Subtract(1) // console.log() => 1
but if you wrap Object in async await something like
var Calc = async function () {
// proprties
this.value = 0
// handler's
this.Add = async (__value) => { this.value = this.value + __value; return this }
this.Subtract = async (__value) => { this.value = this.value - __value; return this }
}
(await new Calc()).Add(2).Subtract(1) // console.log() => undefined
(await (await new Calc()).Add(2)).Subtract(1) // console.log() => 1
I know the reason as Promise is returned it need to be resolved for that you just wrap your code inside () and once statement is executed you can continue chain.
What i am looking for.
await newCalc().Add(2).Subtract(1) // console.log() => 1
1 Answer 1
With the caveat that await can only be used inside an async function, the kind of API you want is possible, it's just a bit more complicated.
Plenty of libraries such as knex, jQuery and nightmare.js implement chaining to compose asynchronous operation. But the chainable methods are not asynchronous. Instead, the asynchronous operation is only carried out at the end of operations (when you want the result) but the methods themselves are synchronous. In the case of knex for example, the asynchronous operation is only carried out when .then() is called.
Here's one way you can do it:
function Calc () {
this.operations = [];
this.value = 0;
}
Calc.prototype = {
add: function (x) {
// schedule a function that performs async addition:
this.operations.push(() => {
return new Promise(ok => {
ok(this.value + x);
});
});
return this;
},
subtract: function (x) {
// schedule a function that performs async subtraction:
this.operations.push(() => {
return new Promise(ok => {
ok(this.value - x);
});
});
return this;
},
// THIS IS WHERE WE DO OUR MAGIC
then: async function (callback) {
// This is finally where we can execute all our
// scheduled async operations:
this.value = 0;
for (let i=0; i<this.operations.length; i++) {
this.value = await operations[i]();
}
return callback(this.value); // since the await keyword will call our
// then method it is the responsibility of
// this method to return the value.
}
}
Now you can use it like this:
async function main () {
let x = await new Calc().add(2).subtract(1);
console.log(x);
}
main();
Note that the code above is functionally equivalent to:
new Calc().add(2).subtract(1).then(x => console.log(x));
4 Comments
operations array when then is called, and all operations doneAdd and Subtract modifies c: const c=new Calc();c.Add(2).Subtract(1);c.then();c.then();c.then(()=>console.log(c.value)), it will log 3!
Calcnot a class?asyncin front of anything does not make sense. Even if those opsAddandSubtractasyncwhy does theCalcfunction isasync. And doubleawaitwhy? what is it that u need to accomplish here.