简体   繁体   English

如何在javascript ES6类中链接异步方法

[英]How to chain async methods in javascript ES6 classes

I want to chain methods from a class. 我想从类中链接方法。 I have o problems with synchronous methods, but I don't know how to do it with asynchronous methods. 我有同步方法的问题,但我不知道如何使用异步方法。

For example, this class: 例如,这个类:

class Example {

  constructor() {
    this.val = 0
  }

  async () {
    setTimeout(() => {
      this.val += 1
      return this
    }, 5000)
  }

  sync () {
    this.val += 1
    return this
  }

  check () {
    console.log('checker', this.val)
    return this
  }

}

This works: 这有效:

new Example().sync().check()
> 1

But this doesn't work: 但这不起作用:

new Example().async().check()
> TypeError: Cannot read property 'check' of undefined

PS I want chaining, not Hell Callbacks. PS我想要链接,而不是地狱回调。

I expect that you want to call check() after the timeout has expired. 我希望你想在超时到期后调用check() The problem is that forks off, and you can't immediately have something available to return. 问题是,分叉,你不能立即有东西可以返回。

You could pass in check() as a callback: 你可以传入check()作为回调:

class Example {

  constructor() {
    this.val = 0
  }

  async (callback) {
    setTimeout(() => {
      this.val += 1
      callback()
    }, 5000)
  }

  sync () {
    this.val += 1
    return this
  }

  check () {
    console.log('checker', this.val)
    return this
  }

}

// execution
var ex = new Example();
ex.async(ex.check)

... or a promise ......或承诺

class Example {

  constructor() {
    this.val = 0
  }

  async (callback) {
    var deferred = Q.defer()
    setTimeout(() => {
      this.val += 1
      deferred.resolve();
    }, 5000)
    return deferred.promise;
  }

  sync () {
    this.val += 1
    return this
  }

  check () {
    console.log('checker', this.val)
    return this
  }

}

// execution
var ex = new Example()
ex.async().then(() => ex.check())

... Or you could use ES6 generators ......或者你可以使用ES6发电机

If all you want is new Example().async().check() to work, all you need to do is return this after you call setTimeout. 如果你想要的只是new Example().async().check()工作,你需要做的就是在调用setTimeout后return this Ex: 例如:

async () {
  setTimeout(() => {
    this.val += 1
  }, 5000)
  return this
}

The return this inside the timeout isn't necessary, since it'll be executing on its own. 在超时内return this是没有必要的,因为它将自己执行。 It's basically running stand alone at that point. 它基本上是独立运行的。

Really, if you want this whole thing to be running async completely, and you're able to control flow of when certain things occur, you need to be using promises to make that happen. 实际上,如果你想让整个事情完全异步运行,并且你能够控制某些事情发生时的流量,你需要使用promises来实现这一点。

If you are using async functions and methods, you are using promises (I suppose you know them, if not please learn about them before reading on). 如果你正在使用async函数和方法,你使用的是promises(我想你知道它们,如果没有,请在阅读之前了解它们)。

You should not use setTimeout inside of an asynchronous function if you consider waiting for it. 如果考虑等待,则不应在异步函数内使用setTimeout Instead, create a promise for the timeout, preferably using a helper function like this: 相反,创建一个超时的承诺,最好使用这样的辅助函数:

function timeout(ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms)
    });
}

Now you can write your method like you'd really want to: 现在你可以像你真正想要的那样编​​写你的方法:

class Example {
  …
  async async () {
    await timeout(5000);
    this.val += 1;
    return this;
  }
  …
}

Of course, as an async function it does not return the instance itself, but a promise for it. 当然,作为async函数,它不会返回实例本身,而是它的承诺。 If you are going to chain, you will have to call it inside of another asynchronous function where you can await that promise: 如果要进行链接,则必须在另一个异步函数中调用它,您可以await该承诺:

(async function() {
    (await (new Example().async())).check();
}());

What you are looking for will be solved most elegantly by Promises . Promises将以最优雅的方式解决您所寻找的问题。 You'll need to likely install a polyfill, like Bluebird or q . 你需要安装一个polyfill,比如Bluebirdq

I would change your async method to: 我会将您的异步方法更改为:

async() {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            this.val += 1;
            resolve(this);
        }, 5000);
    });
}

And your calling code to: 你的主叫代码:

new Example().async().then((instance)=>instance.check());

Unfortunately, until ES7 async functions are nailed down, there won't be an elegant way to do this without some form of callback. 不幸的是,在ES7异步函数被固定之前,如果没有某种形式的回调,就没有一种优雅的方法可以做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM