【问题标题】:Promise in series duplicate code avoiding承诺串联重复代码避免
【发布时间】:2018-02-01 04:16:17
【问题描述】:

使用 javascript 承诺,我必须创建一个需要执行以下功能的 ES6 类

list() {
        if(this.isConnected){
            return ActilityAPI.list().then(result => {
                return result
            });
        }else{
            return this.connect().then(() => {
                return ActilityAPI.list().then(result => {
                    return result
                });
            })
        }
}

如您所见,有一部分代码我需要编写几个。通过同步功能,它会更容易,比如:

list() {
        if(this.isConnected) this.connect()
        return ActilityAPI.list()
}

我想尝试相同的算法,但有希望。我该怎么办?

编辑

感谢 alexmac,我想尝试 ES7 的方式,所以我做了以下:

list() {
        // return new Promise((resolve, reject) => {
        return (async () => {
            if (!this.isConnected) await this.connect();
            return ActilityAPI.list()
        })
}

我也尝试在 list() 之前添加 tje async,但它不会编译

【问题讨论】:

  • 请注意,您的承诺中的 result => { return result } 处理程序实际上什么都不做。
  • list(){ return this.isConnected? ActilityAPI.list(): this.connect().then(() => ActilityAPI.list()) }
  • @Thomas 看起来连接本身就是一个承诺。
  • @JaredSmith 是的,完全正确。有什么意义?
  • @Thomas 那么为什么有一个无关的属性isConnected?只需让this.isConnected 连接函数中的承诺并链接它。

标签: javascript node.js asynchronous promise


【解决方案1】:

作为单行符,感谢三元运算符,您可以这样做:

const list = () => 
    (!this.isConnected ? 
        this.connect() : 
        Promise.resolve())
    .then(() => ActilityAPI.list())

Promise.resolve 创建一个新的 Promise 并立即解析它,调用 then-Handler。

在一个类中,const 显然已经过时了。

但是在阅读了其他答案之后,我认为要走的路是将检查和连接承诺提取到自己的函数中,就像这样:

class {
    connectIfNotConnected = () => 
        !this.isConnected ? 
            this.connect() : 
            Promise.resolve();

    list = () =>
        this.connectIfNotConnected()
        .then(() => ActilityAPI.list())
}

因为如果API上有更多的操作,你需要再次检查,这样你就有一个函数可以做到这一点,无论如何。 它只需要在准备好时返回一个 Promise。

【讨论】:

  • 不鼓励仅使用代码的答案;你介意解释一下你在做什么,以便未来的读者更容易理解吗?
【解决方案2】:

以下是重写代码的简洁方法:

list() {
    const ensureConnected = this.isConnected
        ? Promise.resolve()
        : this.connect();

    return ensureConnected.then(() => ActilityAPI.list());
}

【讨论】:

  • 您在then(ActilityAPI.list); 中丢失了上下文,如果在list 中使用this,它将指向另一个对象。
【解决方案3】:

如果您想使用 ES6 类和 ES7 async/awit,代码可能如下所示:

class db {
  async list() {
    if (!this.isConnected) {
      await this.connect();
    }
    return ActilityAPI.list();
 }

【讨论】:

  • 如果list()是一个独立的箭头函数,那么this是如何引用父对象的呢?此外,在使用箭头函数时,您不需要 self = this hack,因为 this 的值将保留在箭头函数中。
  • @alexmac 我想在课堂上尝试 es7 的方式,看起来更易读。你能告诉我我的编辑吗?
  • @AtesGoral 你是对的,因为在使用箭头函数时不需要保存上下文。
【解决方案4】:

你会想做这样的事情:

class Foo {
  constructor () {
    this.connected = someFunctionThatConnects();
  }

  list () {
    return this.connected.then(() => ActilityAPI.list());
  }
}

someFunctionThatConnects 返回一个承诺。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-07
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多