代码之家  ›  专栏  ›  技术社区  ›  laptou

我应该返回Rust等待吗?

  •  0
  • laptou  · 技术社区  · 5 年前

    在JavaScript中,异步代码是用Promises和 async / await 语法类似于Rust。通常认为返回是多余的(因此不鼓励) 等待一个Promise,当它可以简单地返回时(即当一个异步函数作为另一个函数中的最后一件事执行时):

    async function myFn() { /* ... */ }
    
    async function myFn2() {
      // do setup work
    
      return await myFn()
      // ^ this is not necessary when we can just return the Promise
    }
    

    我想知道类似的模式是否适用于Rust。我应该更喜欢这个吗:

    pub async fn my_function(
        &mut self,
    ) -> Result<()> {
        // do synchronous setup work
    
        self.exec_command(
            /* ... */
        )
        .await
    }
    

    或者这个:

    pub fn my_function(
        &mut self,
    ) -> impl Future<Output = Result<()>> {
        // do synchronous setup work
    
        self.exec_command(
            /* ... */
        )
    }
    

    前者对我来说更符合人体工程学,但我怀疑后者可能更具表现力。是这样吗?

    0 回复  |  直到 5 年前
        1
  •  3
  •   Shepmaster Lukas Kalbertodt    4 年前

    这两种变体之间的一个语义差异是,在第一种变体中,同步设置代码仅在等待返回的future时运行,而在第二种变体中它将在函数被调用时立即运行:

    let fut = x.my_function();
    // in the second variant, the synchronous setup has finished by now
    ...
    let val = fut.await;  // in the first variant, it runs here
    

    为了使差异明显,同步设置代码必须有副作用,并且在调用异步函数和等待它返回的未来之间需要有延迟。

    除非你有特定的理由立即执行前导码,否则请使用async函数,即第一个变体。它使函数的可预测性略有提高,并且在函数重构后更容易添加更多等待。

        2
  •  1
  •   Stephen Carman    4 年前

    两者之间没有真正的区别,因为async只是解析为 impl Future<Output=Result<T, E>> 我不认为两者之间有任何有意义的性能差异,至少在我对两者的经验用法中是这样。

    如果你问的是风格偏好,那么在我看来,第一种是首选的,因为我觉得类型更清晰,我也同意它更符合人体工程学。