为什么等待之后的代码不立即运行?它不应该是非阻塞的吗? [英] Why doesn't the code after await run right away? Isn't it supposed to be non-blocking?

查看:24
本文介绍了为什么等待之后的代码不立即运行?它不应该是非阻塞的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解异步和等待在幕后是如何工作的。我知道我们有承诺,通过使用";Then;函数,我们可以在承诺解析后放置我们需要做的所有工作,从而实现我们的非阻塞代码。我们想要做的工作与承诺的并行,我们只是在Then函数之外编写它。因此,代码变成了非阻塞的。但是,我不明白asyncawait是如何生成非阻塞代码的。

async function myAsyncFunction() {
  try {
    let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    // It will not run this line until it resolves await.
    let result = 2 + 2;
    return data;
  }catch (ex){
    return ex;
  }
}

请参阅上面的代码。在解决API调用之前,我无法继续前进。如果它让我的代码阻塞代码,它还有什么比承诺更好的呢?或者,我是否遗漏了asyncawait?我应该将不依赖于等待调用的代码放在哪里?这样它就可以在不等待暂停执行的情况下继续工作?

我正在添加一个承诺代码,我希望在一个等待的异步示例中复制该代码。

function myPromiseAPI() {
  myAPICall('https://jsonplaceholder.typicode.com/posts/1')
    .then(function (data) {
        // data
    });
   // runs parallel
  let result = 2 + 2;
}

推荐答案

顾名思义,await关键字将导致函数"等待",直到其承诺解析后才执行下一行。await的全部目的是让代码等到操作完成后再继续。

这与阻塞代码的区别在于,函数外部的世界可以在函数等待异步操作完成时继续执行。

asyncawait只是承诺之上的语法糖。它们允许您编写看起来很像普通同步代码的代码,尽管它在幕后使用了承诺。如果我们将您的示例转换为与承诺明确相关的内容,它将如下所示:

function myAsyncFunction() {
  return myAPICall('https://jsonplaceholder.typicode.com/posts/1')
    .then(function (data) {
       let result = 2 + 2;
       return data;
    })
    .catch(function (ex) {
        return ex;
    });
}

正如我们在这里看到的,let result = 2 + 2;行在.then()处理程序中,这意味着它在myAPICall()解析之前不会执行。使用await时也是如此。await只是为您抽象.then()

要记住的一件事(我认为您正在寻找的要点)是您不必立即使用await。如果您这样编写函数,则可以立即执行let result = 2 + 2;行:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    // just starting the API call and storing the promise for now. not waiting yet
    let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');

    let result = 2 + 2;

    // Executes right away
    console.log('result', result);

    // wait now
    let data = await dataP;

    // Executes after one second
    console.log('data', data);

    return data;
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

经过一些澄清之后,我可以看出您真正想知道的是如何避免一个接一个地等待两个异步操作,而是让它们并行执行。事实上,如果您在使用一个await之后使用另一个await,则第二个await直到第一个完成后才会开始执行:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    // logs after one second
    console.log('data1', data1);

    let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
    // logs after one more second
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

要避免这种情况,您可以启动两个异步操作,在不等待它们的情况下执行它们,并将它们的承诺赋给一些变量。然后你可以等待这两个承诺:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');
    // both lines execute right away
    let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');

    let data1 = await dataP1;
    let data2 = await dataP2;

    // logs after one second
    console.log('data1', data1);
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

一种替代方法是使用Promise.all()和一些数组分解:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    // both myAPICall invocations execute right away
    const [data1, data2] = await Promise.all([
        myAPICall('https://jsonplaceholder.typicode.com/posts/1'), 
        myAPICall('https://jsonplaceholder.typicode.com/posts/2'),
    ]);

    // logs after one second
    console.log('data1', data1);
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

这篇关于为什么等待之后的代码不立即运行?它不应该是非阻塞的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆