首页 > 解决方案 > 异步链接模式

问题描述

考虑以下情况:

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

但是如果你将 Object 包装在 async await 中,比如

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

我知道返回 Promise 的原因,它需要解决,因为您只需将代码包装在 () 中,一旦执行语句,您就可以继续链。

我在找什么。

await newCalc().Add(2).Subtract(1) // console.log() => 1

标签: javascriptnode.js

解决方案


await使用只能在函数内部使用的警告,async您想要的 API 类型是可能的,只是稍微复杂一点。

大量的库,例如knex,jQuerynightmare.js实现链式组合异步操作。但是可链接的方法不是异步的。相反,异步操作仅在操作结束时执行(当您想要结果时),但方法本身是同步的。例如knex,异步操作仅在.then()被调用时执行。

这是您可以做到的一种方法:

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.
    }
}

现在你可以像这样使用它:

async function main () {
    let x = await new Calc().add(2).subtract(1);
    console.log(x);
}
main();

请注意,上面的代码在功能上等同于:

new Calc().add(2).subtract(1).then(x => console.log(x));

推荐阅读