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 值,而不是 doSomethingChainedreturn 值,因为 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);