一起使用 async await 和 .then

Pix*_*aul 33 javascript asynchronous node.js promise async-await

使用async/await.then().catch()一起使用是否有任何危害,例如:

async apiCall(params) {
    var results = await this.anotherCall()
      .then(results => {
        //do any results transformations
        return results;
      })
      .catch(error => {
        //handle any errors here
      });
    return results;
  }
Run Code Online (Sandbox Code Playgroud)

Bri*_*cky 48

不想复活死者,但想指出与链条await一起使用then意味着结果:

const x = await someAsyncFn().then(() => doSomeLogging());
Run Code Online (Sandbox Code Playgroud)

的值x被指定为返回值 .then(即undefined,如果doSomeLogging为空),这对我来说不是非常直观。

  • 如果您要等待“.then”中的值,那么添加“await”有什么意义?代码如何工作,“x”的值是多少? (2认同)
  • @MohammedShahed 没有意义,这只是人们在不太熟悉这两种范式时可能会做的事情。关键是这两种不同的方法基本上做同样的事情,但它们并不总是能够很好地协同工作。 (2认同)

sli*_*wp2 26

我总是使用async/awaitand.catch()而不是使用 async/awaitandtry/catch来紧凑地编写代码。

async function asyncTask() {
  throw new Error('network')
}
async function main() {
  const result = await asyncTask().catch(error => console.error(error));
  console.log('result:', result)
}

main();
Run Code Online (Sandbox Code Playgroud)

如果你想在错误发生时得到一个回退值,你可以忽略错误并在.catch()方法内部返回一个值

async function asyncTask() {
  throw new Error('network')
}
async function main() {
  const result = await asyncTask().catch(_ => 'fallback value');
  console.log('result:', result)
}

main();
Run Code Online (Sandbox Code Playgroud)

  • 您的代码在使用“await”的同时不包含任何“then”子句,这正是问题所在! (2认同)

Shu*_*ubh 19

异步函数可以包含一个 await 表达式,该表达式暂停异步函数的执行并等待传递的 Promise 的解析,然后恢复异步函数的执行并返回解析的值。

正如您从下面的示例中看到的,您可以使用两种方法来处理等待结果和错误,关键字 await 使 JavaScript 等待,直到该承诺解决并返回其结果(您从已解决的承诺中获得一种)。因此,没有任何危害(我不完全理解你在这里所说的伤害)。

function returnpromise(val) {
  return new Promise((resolve, reject) => {
    if (val > 5) {
      resolve("resolved"); // fulfilled
    } else {
      reject("rejected"); // rejected
    }
  });
}

//This is how you handle errors in await
async function apicall() {
  try {
    console.log(await returnpromise(5))
  } catch (error) {
    console.log(error)
  }
}

async function apicall2() {
  let data = await returnpromise(2).catch((error) => {
    console.log(error)
  })
}

apicall2();
apicall();
Run Code Online (Sandbox Code Playgroud)

如需进一步参考,请查看- MDN DOCS


Pet*_*uan 12

我认为混合使用 async/await + then 不是一个好主意。尤其是当你专注于 async func 的资源时,混合使用会带来一些悄然扭曲你的资源的风险。

例子:

const res = await fetchData().then(()=>{return "something else"}).catch((err)=>{});

console.log(res); // not expected res data but something else
Run Code Online (Sandbox Code Playgroud)

所以,混合使用是危险的,顺便说一下,它会损害阅读代码。

  • 我同意混合“await”和“then”会损害可读性,但我不明白你在这里的例子。 (3认同)
  • 建议:添加代码围栏和语言标识符以突出显示代码并使其更具可读性。 (2认同)

ggo*_*len 12

我认为整个线程对于“伤害”的含义存在一些困惑。如果你将伤害定义为(仅仅)“OP 的确切代码运行正常吗?”,那么它就没有伤害。

然而,如果你将危害定义为“这是一种难以阅读、容易出错的反模式,往往会导致错误,并且从来没有真正必要诉诸”,那么它确实是有害的。

Stack Overflow 上有无数的问题,其中 OP 混合在一起.thenawait最终出现了错误。我选择了一些内容包含在这篇文章的底部。

作为一个简单的经验法则,永远不要将and组合在一个函数中awaitthen。最好的情况是,它比使用其中之一更难阅读,最坏的情况是,它隐藏了一个错误,通常与错误处理有关。

一般来说,更喜欢async/await而不是.then。如果您很难决定何时使用哪个,请随意更进一步并.then完全避免.catch

也就是说,我喜欢偶尔使用.then它,当涉及错误处理时,它可以稍微不那么冗长,并且不需要访问无法轻松通过链传递的对象的状态

fetch("https://www.example.com")
  .then(response => {
     if (!response.ok) {
       throw Error(response.statusText);
     }

     return response.json();
   )
  .then(data => console.log(data))
  .catch(err => console.error(err));
Run Code Online (Sandbox Code Playgroud)

对我来说似乎比以下更干净:

(async () => {
  try {
    const response = await fetch("https://www.example.com");
  
    if (!response.ok) {
      throw Error(response.statusText);
    }

    console.log(response.json());
  }
  catch (err) {
    console.error(err);
  }
})();
Run Code Online (Sandbox Code Playgroud)

使用 top-level await,底层代码变得更有吸引力,尽管在实践中,您通常编写一个函数。

我同意这个答案给出的一个例外,即偶尔.catchawait链上使用以避免有点难看的try/ catch

以下是此功能何时有用的示例:

const fs = require("node:fs/promises");

const exists = async pathName =>
  !!(await fs.stat(pathName).catch(() => false));
Run Code Online (Sandbox Code Playgroud)

可能比///async版本await更好trycatch

const exists = async pathName => {
  try {
    await fs.stat(pathName);
    return true;
  }
  catch (err) {
    return false;
  }
};
Run Code Online (Sandbox Code Playgroud)

...或者也许不取决于你是否觉得这个catch版本太聪明了。

请注意,这里没有.thenandawait混合,只是.catch而不是try/ except。这里起作用的一般启发是“更平坦更好”(.catchtry/更平坦catch并且await比 更平坦.then)。

(是的,这个例子有点人为,因为有一种非常干净的方法可以单独使用.then/.catch来完成这个特定的任务,但是该模式可能会不时出现在其他上下文中)

如果有任何疑问,请遵守“绝不混合”的规则。


await正如所承诺的,这里是我所看到的一小部分由混合和then(加上一些其他承诺反模式)引起的混乱的示例:

以及相关主题:


Abd*_*ssi 10

如果您使用 Async/await,则不需要链接,只需.then()将返回的结果存储resolve()在变量中(response在示例中),但如果您想处理错误,则必须尝试/捕获代码:

async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}
Run Code Online (Sandbox Code Playgroud)

在你的承诺中使用:

throw new Error("oops!");

或者

Promise.reject(new Error("Whoops!"));


归档时间:

查看次数:

25548 次

最近记录:

4 年,1 月 前