ES 6 Harmony 异步 class 方法链接
ES 6 Harmony async class method chaining
这是一个简单的JavaScript示例:
class Test {
constructor() {
this.a = 0;
this.b = 1;
}
doSomething = async () => {
await this.doSomethingChained(1)
.doSomethingChained(2)
.doSomethingChained(3);
};
doSomethingChained = async (x) => {
this.a = this.a + x;
console.log('a is', this.a);
return this;
};
}
然后开始使用测试方法不过这没关系
test('Vorgang erfassen', async t => {
const t1 = new Test();
await t1.doSomething();
控制台包含以下内容:
a is 1
TypeError: _this2.doSomethingChained(...).doSomethingChained is not a function
我不明白为什么 this.a
有效,但 return this
无效。
我当然可以一个接一个地开始这个方法,但我更愿意使用链接。
doSomething = async () => {
await this.doSomethingChained(1);
await this.doSomethingChained(2);
await this.doSomethingChained(3);
};
很有魅力。
a is 1
a is 3
a is 6
您可以像下面这样链接您的承诺:
doSomething = async () => {
await this.doSomethingChained(1)
.then(() => this.doSomethingChained(2))
.then(() => this.doSomethingChained(3));
};
根据此语法的链接:
this.doSomethingChained(1).doSomethingChained(2)
... 根据定义是同步的:JavaScript 将同步评估参数和函数调用;你对此无能为力。所以这种语法只是不适合异步代码。
异步代码本质上依赖于回调。甚至 promises 都涉及回调的异步执行。对于 await
这不太明显,但是,相应的 async
函数的执行上下文会异步恢复,在解析 await
后继续执行。
对于你的问题:
I don't understand why this.a
works, but return
this not.
return this
确实有效,但根据规范,async
函数中return
语句提供的值定义了promised 值,而不是 doSomethingChained
的 return 值,因为 async
函数 always return 是一个承诺(同步)。
所以在您的代码中,doSomethingChained
的(同步!)return 值是一个承诺,而不是 this
。这解释了您收到错误的原因。
请注意,async
函数在没有 await
时不是很有用。没有它你还不如使用一个普通的函数。
我认为您可以使用 Promise.all
来链接承诺
class Laundry {
constructor() {
this.queue = [];
this.clothes = [];
}
addClothes(cloth) {
this.clothes.push(cloth);
return this;
}
removeClothes(cloth) {
const clothIndex = this.clothes.findIndex(value => value === cloth);
this.clothes.splice(clothIndex, 1);
return this;
}
wash() {
this.clothes = 'washed';
const item = new Promise(resolve => setTimeout(() => resolve(1), 3000)).catch()
this.queue.push(item);
return this;
}
rinse() {
this.clothes = 'rinsed';
const item = new Promise(resolve => setTimeout(() => resolve(2), 2000)).catch()
this.queue.push(item);
return this;
}
finish() {
return Promise.all(this.queue);
}
}
module.exports = Laundry;
然后这样调用...
const Laundry = require('./laundry');
const laundry = new Laundry();
// class chain methods...
laundry.wash().rinse().finish().then(console.log).catch(console.error);
这是一个简单的JavaScript示例:
class Test {
constructor() {
this.a = 0;
this.b = 1;
}
doSomething = async () => {
await this.doSomethingChained(1)
.doSomethingChained(2)
.doSomethingChained(3);
};
doSomethingChained = async (x) => {
this.a = this.a + x;
console.log('a is', this.a);
return this;
};
}
然后开始使用测试方法不过这没关系
test('Vorgang erfassen', async t => {
const t1 = new Test();
await t1.doSomething();
控制台包含以下内容:
a is 1
TypeError: _this2.doSomethingChained(...).doSomethingChained is not a function
我不明白为什么 this.a
有效,但 return this
无效。
我当然可以一个接一个地开始这个方法,但我更愿意使用链接。
doSomething = async () => {
await this.doSomethingChained(1);
await this.doSomethingChained(2);
await this.doSomethingChained(3);
};
很有魅力。
a is 1
a is 3
a is 6
您可以像下面这样链接您的承诺:
doSomething = async () => {
await this.doSomethingChained(1)
.then(() => this.doSomethingChained(2))
.then(() => this.doSomethingChained(3));
};
根据此语法的链接:
this.doSomethingChained(1).doSomethingChained(2)
... 根据定义是同步的:JavaScript 将同步评估参数和函数调用;你对此无能为力。所以这种语法只是不适合异步代码。
异步代码本质上依赖于回调。甚至 promises 都涉及回调的异步执行。对于 await
这不太明显,但是,相应的 async
函数的执行上下文会异步恢复,在解析 await
后继续执行。
对于你的问题:
I don't understand why
this.a
works, butreturn
this not.
return this
确实有效,但根据规范,async
函数中return
语句提供的值定义了promised 值,而不是 doSomethingChained
的 return 值,因为 async
函数 always return 是一个承诺(同步)。
所以在您的代码中,doSomethingChained
的(同步!)return 值是一个承诺,而不是 this
。这解释了您收到错误的原因。
请注意,async
函数在没有 await
时不是很有用。没有它你还不如使用一个普通的函数。
我认为您可以使用 Promise.all
来链接承诺 class Laundry {
constructor() {
this.queue = [];
this.clothes = [];
}
addClothes(cloth) {
this.clothes.push(cloth);
return this;
}
removeClothes(cloth) {
const clothIndex = this.clothes.findIndex(value => value === cloth);
this.clothes.splice(clothIndex, 1);
return this;
}
wash() {
this.clothes = 'washed';
const item = new Promise(resolve => setTimeout(() => resolve(1), 3000)).catch()
this.queue.push(item);
return this;
}
rinse() {
this.clothes = 'rinsed';
const item = new Promise(resolve => setTimeout(() => resolve(2), 2000)).catch()
this.queue.push(item);
return this;
}
finish() {
return Promise.all(this.queue);
}
}
module.exports = Laundry;
然后这样调用...
const Laundry = require('./laundry');
const laundry = new Laundry();
// class chain methods...
laundry.wash().rinse().finish().then(console.log).catch(console.error);