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

时间:2015-09-18 15:23:21

标签: javascript node.js class ecmascript-6 chaining

我想从类中链接方法。我有同步方法的问题,但我不知道如何使用异步方法。

例如,这个类:

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
  }

}

这有效:

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

但这不起作用:

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

P.S。我想要链接,而不是地狱回调。

4 个答案:

答案 0 :(得分:6)

我希望您在超时过期后调用check()。问题是叉子关闭了,你不能马上有东西可以返回。

您可以传递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)

......或承诺

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())

......或者你可以使用ES6发电机

答案 1 :(得分:5)

如果你想要的只是private class myWebViewBrowser extends WebViewClient { @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { Log.e(String.valueOf(error.getErrorCode()), error.getDescription().toString()); view.loadDataWithBaseURL( "file:///android_asset/", html, "text/html","utf-8", null ); } } ,你需要做的就是在调用setTimeout之后new Example().async().check()。例如:

return this

超时内的async () { setTimeout(() => { this.val += 1 }, 5000) return this } 是不必要的,因为它将自行执行。它在那时基本上独立运行。

真的,如果你想让整个事情完全异步运行,并且你能够控制某些事情发生时的流量,你需要使用promises来实现这一点。

答案 2 :(得分:4)

如果您正在使用async函数和方法,那么您正在使用promises(我想您知道它们,如果没有,请在阅读之前了解它们。)

如果您考虑等待它,则不应在异步函数内部使用setTimeout。相反,创建一个超时的承诺,最好使用这样的辅助函数:

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

现在你可以像你一样写下你的方法:

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

当然,作为async函数,它不返回实例本身,而是它的承诺。如果要进行链接,则必须在另一个异步函数内调用它,您可以await承诺:

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

答案 3 :(得分:1)

Promises最优雅地解决您所寻找的问题。您可能需要安装填充,例如Bluebirdq

我会将您的异步方法更改为:

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

您的主叫代码为:

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

不幸的是,在ES7异步功能被确定之前,如果没有某种形式的回调,这将是一种优雅的方式。