NodeJS Async / await与哪一个性能最好?

z5btuh9x  于 2023-04-11  发布在  Node.js
关注(0)|答案(9)|浏览(277)

我有一个简单的JavaScript代码,它在API中执行请求并返回响应,简单。但在这种情况下,我将有数千个请求。那么,哪一个代码选项将执行得更好,为什么。还有,哪一个是推荐的好做法?
第一个选项是使用.then来解析promise,第二个选项是使用async / await。
在我的测试中,这两个选项的结果非常相似,没有显著差异,但我不确定规模。

// Using then
doSomething(payload) {
  const url = 'https://link-here/consultas';
  return this.axios.get(url, {
    params: {
      token: payload.token,
      chave: payload.chave,
    },
   }).then(resp => resp.data);
}

// Using Async / await
async doSomething(payload) {
   const url = 'https://link-here/consultas';
   const resp = await this.axios.get(url, {
   params: {
     token: payload.token,
     chave: payload.chave,
    },
 });
 return resp.data;
}

任何解释都将是很有价值的。

vwkv1x7d

vwkv1x7d1#

从性能的Angular 来看,await只是.then()的内部版本(做基本相同的事情)。选择一个而不是另一个的原因与性能无关,但与所需的编码风格或编码便利性有关。当然,解释器内部有a few more opportunities to optimize thingsawait,但这不太可能是你决定使用哪一个的方式。如果其他条件相同,我会选择await,因为上面提到的原因。但是,我首先会选择哪一个使代码更容易编写、理解、维护和测试。
如果使用得当,await通常可以是save you a bunch of lines of code making your code simpler to read, test and maintain,这就是它被发明的原因。
这两个版本的代码之间没有任何有意义的区别。当axios调用成功或出错时,两者都能获得相同的结果。
如果你有多个连续的异步调用需要序列化,那么await可以带来更多的便利。然后,而不是将它们每个都放在.then()处理程序中以正确地链接它们,你可以使用await并拥有更简单的代码。
await.then()的一个常见错误是忘记了正确的错误处理。如果你在这个函数中的错误处理只是返回被拒绝的promise,那么你的两个版本都是这样做的。但是,如果你在一行中有多个异步调用,并且你想做比返回第一个拒绝更复杂的事情,那么error handling techniques for await and .then() / .catch()是完全不同的,并且哪个看起来更简单将取决于情况。

px9o7tmv

px9o7tmv2#

await.then将给予非常不同的结果,并且应该用于不同的原因。
await会等待一些东西,然后继续到下一行。它也是两个中比较简单的一个,因为它的行为更像是同步行为。执行步骤#1,等待,然后继续。

console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");

.then从原始调用中分离出来,并在自己的作用域中开始操作,并将在原始作用域无法预测的时间更新。如果我们可以暂时抛开语义,它是“更异步的”,因为它离开了旧的作用域并分支到新的作用域。

console.log("Runs first.");
SomeFunction().then((value) => {console.log("Runs last (probably). Didn't use await on SomeFunction().")})
console.log("Runs second (probably).");
qvsjd97n

qvsjd97n3#

作为对@user280209答案的更多解释,让我们考虑以下返回promise的函数,并将其执行与.then()async await进行比较。

function call(timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`This call took ${timeout} seconds`);
      resolve(true);
    }, timeout * 1000);
  });
}

.then()

(async () => {
  call(5).then((r) => {
    console.log(r);
  });
  await call(2); //This will print result first
  await call(1);
})();

运行上述调用时,日志将

This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true

正如我们所看到的,.then()并没有暂停下面一行的执行,直到它完成。

async/wait

(async () => {
  await call(5); //This will print result first
  await call(2); 
  await call(1);
})();

当运行上述功能时,日志将

This call took 5 seconds
This call took 2 seconds
This call took 1 seconds

所以我认为如果你的promise的结果不会在下面的行中使用,.then()可能会更好。

wlp8pajw

wlp8pajw4#

对于那些说await会阻塞代码直到异步调用返回的人来说,你没有抓住重点。“await”是promise.then()的语法糖。它实际上是将你的函数的其余部分 Package 在它为你创建的promise的then块中。没有真实的的“阻塞”或“等待”。

run();

async function run() {
    console.log('running');
    makePromises();
    console.log('exiting right away!');
}

async function makePromises() {
    console.log('make promise 1');
    const myPromise = promiseMe(1)
    .then(msg => {
        console.log(`What i want to run after the promise is resolved ${msg}`)
    })
    console.log('make promise 2')
    const msg = await promiseMe(2);
    console.log(`What i want to run after the promise is resolved via await ${msg}`)
}   

function promiseMe(num: number): Promise<string> {
    return new Promise((resolve, reject) => {
        console.log(`promise`)
        resolve(`hello promise ${num}`);
    })
}

makePromises中的await行不会阻塞任何东西,输出为:

  • 运行
  • 许下诺言1
  • 许诺
  • 许下诺言2
  • 许诺
  • 马上离开!
  • promise解析后我想运行的hello promise 1
  • 我希望在promise之后运行的内容通过await hello promise 2解析
1sbrub3j

1sbrub3j5#

实际上,Await/Async可以更有效地执行Promise。then()在执行后失去了它被调用的范围,您正在将回调附加到回调堆栈。
它导致的是:系统现在必须存储一个引用,指向.then()被调用的位置。在错误的情况下,它必须正确地指向错误发生的位置,否则,如果没有作用域(因为系统在调用Promise后恢复执行,等待稍后返回.then()),它就无法指向错误发生的位置。
Async/Await挂起调用它的方法的exection,从而保留引用。

wnrlj8wa

wnrlj8wa6#

如果我们只考虑性能(耗时),那么它实际上取决于你的操作是串行的还是并行的。如果你的任务是串行的,那么await和. then之间没有区别。但是如果你的任务是并行的,那么.then将花费更少的时间。考虑下面的例子

let time = Date.now();

// first task takes 1.5 secs 
async function firstTask () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
        },1500)
    })
}

// second task takes 2 secs 
async function secondTask () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
        },2000)
    })
}

// using await
async function call(){
    const d1 = await firstTask();
    const d2 = await secondTask();
    console.log(Date.now()-time, d1+d2)
}
call()

// using .then
async function call2(){
    let d1=null,d2=null;
    firstTask().then(data => {
        d1=data;
        if(d2){
            console.log(Date.now()-time, d1+d2);
        }
    })
    secondTask().then(data => {
        d2=data;
        if(d1){
            console.log(Date.now()-time, d1+d2);
        }
    })
}
call2()

下面是两个任务,第一个任务需要1.5秒,第二个任务需要2秒。Call函数使用await where,而call2函数使用.then。输出如下

From call2  2012 3
From call  3506 3

希望能帮上忙。

dw1jzc5e

dw1jzc5e7#

据我所知。那么()和await不是一回事。异步函数在promise被解析/拒绝之前不会继续执行下一个命令,因为它基本上是生成器的实现。相反,在.then的情况下(),该函数的执行将继续下一个命令和解决/拒绝回调将被执行“当有时间”也就是当前事件循环(不完全确定该部分)何时完成。
tldr;在一个promise上await和.then()的行为类似,但是当一个promise需要先解析另一个promise时,它们的行为完全不同

k2fxgqgv

k2fxgqgv8#

这个问题已经有很多答案了。但是,为了指出上述答案中的关键信息,根据我的理解,请注意以下几点:

  • 只在不处理错误返回时使用await
  • 如果不需要错误处理,则使用await
  • 如果返回的错误消息或数据对于调试/或正确的错误处理至关重要,则使用.then .catch,而不是try catch for await
    从下面的代码示例中选择任何首选方法
const getData = (params = {name: 'john', email: 'ex@gmail.com'}) => {
  return axios.post(url, params);
}

// anywhere you want to get the return data

// using await

const setData = async () => {

  const data = await getData();
  
  }
  
  // to handle error with await
  const setData = async () => {
    try {
      const data = await getData();
      }
     catch(err) {
        console.log(err.message);
     }
  }
  
   // using .then .catch
  const setData = () => {
 
      var data; 
      getData().then((res) => { 
        data = res.data; console.log(data)
      }).catch((err) => {
        console.log(err.message);
      });

  }
f4t66c6m

f4t66c6m9#

使用await将暂停执行,直到promise得到解决。如果您不使用await并将promise存储在变量中,那么您可以随时await它(就像下面例子中的function a()),这是你不能用then()方法来实现的。在某些情况下,以这种方式使用async/await可以保存一些时间。O操作在promise中执行。

// Simulating the I/O operation that takes 5 secs.
function load(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("done");
        },5000)
    })
}
    
async function a(){
    const startTime = new Date();
    // not using the await right away
    const pr = load();
    // some tasks
    for(let i = 0; i < 30000; i++){
        console.log(i);
    }
    console.log(await pr);
    console.log("total duration : " , new Date() - startTime)
}

async function b(){
    const startTime = new Date();
    // using the await right away
    console.log(await load());
    // some tasks
    for(let i = 0; i < 30000; i++){
        console.log(i);
    }
    console.log("total duration : " , new Date() - startTime)
}

a(); //took 11193 ms
b(); //took 16080 ms

相关问题