异步/等待vs承诺

时间:2019-07-29 12:13:34

标签: javascript node.js asynchronous promise async-await

与最佳实践相混淆。

Using async-await is better than using promises.对吗?

如何确定aync/awaitpromises的使用?

下面我只写了两个代码段。一个使用aync/await,另一个不使用它。

哪个会更快?

案例1的优势是什么?

哪个是最新的方法和相对于另一个的优势?

案例1

var promise1 = rp('https://api.example.com/endpoint1');
var promise2 = rp('https://api.example.com/endpoint2');

var response1 = await promise1;
var response2 = await promise2;
return response1 + ' ' + response2;

案例2

var promise1 = rp('https://api.example.com/endpoint1');
var promise2 = rp('https://api.example.com/endpoint2');

return Promise.all([promise1, promise2])
.then(function(values){
    return values[0] + values[1];
});

5 个答案:

答案 0 :(得分:5)

  

使用async-await比使用promises更好

不。 asyncawait是可帮助您管理承诺的工具。

  

哪个会更快?

不可能有明显的区别

  

案例1的优势是什么?

有些人会认为它更容易理解。其他人可能会不同意。

答案 1 :(得分:2)

Async / await转换为引擎盖下的Promise。

因此,两者的性能是相同的。

除非有一些技术上的限制,否则您应该始终使用async / await,因为它更容易理解。

现在,正如其他提到的那样,目前两个代码示例不相等。 但是由于您使用的是await,这意味着您的rp()返回了诺言。因此,您可以将第一种情况改写为:

let [r1, r2] = await Promise.all([promise1, promise2])
return r1 + r2

要获得相同的结果。

答案 2 :(得分:0)

  

使用async-await比使用promise更好。

  

哪个会更快?

  

哪一种是最新的方法和相对于另一种方法的优势?

语法和您的方法中的任何一个都不提供相对于其他方法的任何特殊优势,但是此外,您的方法不能很好地展现您的意图。您无需保留对promise的明确引用即可同时获得其结果:

const [response1, response2] = await Promise.all([
  rp('https://api.example.com/endpoint1'),
  rp('https://api.example.com/endpoint2')
]);
...

请记住,以上方法必须包含在async函数中。它不能像这种方法那样在顶级范围内存在:

Promise.all([
  rp('https://api.example.com/endpoint1'),
  rp('https://api.example.com/endpoint2')
]).then(([response1, response2]) => {
  ...
});

答案 3 :(得分:0)

所有当前答案当然是正确的,但请记住一些差异。

当前,在您的两个解决方案中,承诺都是并行调用的。这可能会导致一些错误。

考虑这种情况(对情况1进行一些修改):

var response1 = await rp('https://api.example.com/endpoint1');
var response2 = await rp('https://api.example.com/endpoint2');

return response1 + ' ' + response2;

在上述情况下,promise2将在promise1完成执行之后执行。当promise2启动时,结果是已知的。另一方面,您的案件会在某种竞赛中一起运行。因此,如果在第二次调用rp中包含依赖于在第一次调用rp中执行的某些操作的逻辑,则可能会导致意外结果甚至崩溃。一个很好的例子是写入和读取相同的文件。

让我们考虑以下示例:

function writeToFile()
{
   return new Promise((resolve, reject) => {
      ... // writing to file abc.txt
   };
}

function readFile()
{
   return new Promise((resolve, reject) => {
      ... // reading file abc.txt
   };
}

function raceCondition() 
{
   Promise.all([
       writeToFile(),
       readFile()
   ]);
} 

async function asyncAwait() 
{
   await writeToFile();
   await readFile();
} 

raceCondition()函数可能会导致意外行为,因为readFile可能在writeToFile函数甚至还没有完成写入文件的情况下运行。这可能会导致读取一些旧数据,甚至可能根本不存在文件。

asyncAwait()函数使用异步/等待方法,该方法保证writeToFile()函数在读取开始之前完成其工作。当然,这并不意味着程序会变得同步。同时,还会执行其他操作(例如一些GUI事件处理等)。

然后应将Async / Await视为.then()。then()链的替代方案,而不是Promise.all

答案 4 :(得分:0)

等待用于评估已解决或已拒绝的Promise。因此,使用.then和await的功能是相同的。但是,由于您不会陷入一系列回调,因此await使得代码更具可读性。使用await时,您可以将async函数视为使用await的同步函数。

让我们举个例子。我们有一个API和2个数据库,我们想从其中一个数据库取一个名称,然后插入另一个数据库。为此,我们必须从数据库1中获取数据。等待数据到达客户端,然后通过POST请求将其发送到要插入的API。 [您可以在 ONE 函数服务器端完成所有这些操作,但对于我们来说,我们将提出2个异步提取请求来回答此问题]。如果我们想使用 .then 来解决此问题,它将看起来像这样。

function get_and_set(){
   fetch("https://www.some_api.com/get_random_name")
   .then( response => response.text() )
     .then( name => {
       fetch("https://www.some_api_2.com/insert_name", {
        headers : {
          "Body-Type"    : "application/json",
          "Accept"       : "application/json"
        },
        method : "POST",
        body : JSON.stringify({ name : name })
      })
      .then( set_response => set_response.text() )
        .then( set_response => {
           return set_response;
        })
     )}

}

如果我们选择在await中使用异步函数,则可以这样编写。我个人认为这更具可读性。

async function get_and_set(){
  let response = await fetch("https://www.some_api.com/get_random_name")
  let name = response.text();

  let insert_response = await fetch("https://www.some_api_2.com/insert_name", {
     headers : {
        "Body-Type"    : "application/json",
        "Accept"       : "application/json"
     },
     method : "POST",
     body : JSON.stringify({ name : name })
  });
  let success = insert_response.text();

  return (success); //Return the status of how the insertion went
}