Javascript 异步链接模式

Javascript 异步链接模式,javascript,node.js,Javascript,Node.js,考虑以下情况: 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 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
但是,如果您将对象包装为异步,请等待

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

需要注意的是,
await
只能在
async
函数中使用,您想要的API是可能的,只是有点复杂

大量的库,如
knex
jQuery
dream.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.
    }
}
请注意,上述代码在功能上等同于:

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

需要注意的是,
await
只能在
async
函数中使用,您想要的API是可能的,只是有点复杂

大量的库,如
knex
jQuery
dream.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.
    }
}
请注意,上述代码在功能上等同于:

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

作为第一条评论:为什么你的
Calc
不是一个类?这些操作不是异步的,只是一个一般性的问题,你使用Promises作为计算器有什么特别的原因吗?如果你是通过网络请求获取数字,你可以这样做,但如果你只是在计算数字,似乎没有任何理由。在这里直截了当地说:只是把
async
放在任何东西前面都没有意义。即使那些操作
Add
Subtract
async
为什么
Calc
函数是
async
。而双
等待
为什么?你需要在这里完成什么。作为第一条评论:为什么你的
Calc
不是一个类?这些操作不是异步的。这只是一个一般性的问题,你使用promissions作为计算器有什么特别的原因吗?如果你是通过网络请求获取数字,你可以这样做,但如果你只是在计算数字,似乎没有任何理由。在这里直截了当地说:只是把
async
放在任何东西前面都没有意义。即使那些操作
Add
Subtract
async
为什么
Calc
函数是
async
。而双
等待
为什么?你需要在这里完成什么?和我开始写的一样。。。很好的代码和解释,+1另外,当调用
时,不要忘记清空
操作
数组,然后
调用所有操作done@FZs这取决于你想做什么。例如,Knex不会清空operations数组(或它内部使用的任何数组),以便您可以重用查询对象从dbI agree中再次获取数据,但在这种情况下,保留它将导致一些奇怪的行为。只要在
Add
Subtract
修改
c
时尝试一下:
const c=new Calc();c、 加(2)减(1);c、 然后();c、 然后();c、 然后(()=>console.log(c.value))
,它将记录3!和我开始写的一模一样。。。很好的代码和解释,+1另外,当调用
时,不要忘记清空
操作
数组,然后
调用所有操作done@FZs这取决于你想做什么。例如,Knex不会清空operations数组(或它内部使用的任何数组),以便您可以重用查询对象从dbI agree中再次获取数据,但在这种情况下,保留它将导致一些奇怪的行为。只要在
Add
Subtract
修改
c
时尝试一下:
const c=new Calc();c、 加(2)减(1);c、 然后();c、 然后();c、 然后(()=>console.log(c.value))
,它将记录3!