为什么异步总是返回承诺? [英] Why Does Async Always Return a Promise?

查看:115
本文介绍了为什么异步总是返回承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是理论性的-我没有要解决的具体问题.

This question is theoretical - I have no concrete problem to solve.

话虽如此,为什么async关键字为什么在promise中包装了异步函数的返回值?重点是什么?仅仅是因为await表达式期望一个诺言吗?还是这个决定背后有一些意义/用途?

With that said, why does the async keyword wrap the return value of an async function in a promise? What's the point? Is it ONLY because the await expression expects a promise? Or is there some meaning / use behind this decision?

推荐答案

我以为我会回答这个问题,主要是因为Java语言中的async曾经使我感到困惑,突然间它突然崩溃了,所以我希望这个类比可以帮助您实现这一目标.

I thought i'd answer this primarily because async in Javascript used to confuse the hell out of me, and all of a sudden it snapped, so i hope this analogy may help this happen for you.

您有一个异步事件.这可以是任何事情,可以从服务器上获取某些东西,在浏览器中完成需要花费时间的事情,训练机器学习模型(!),执行使用setTimeout的函数或方法等.

You have an async event. This could be anything, getting something from a server, doing something in the browser that takes time, training a machine learning model (!), executing a function or method that uses a setTimeout etc.

Javascript的美丽以及它在浏览器中运行良好的一个关键原因是,它以一种非常聪明的方式使用了运行于其上的处理器线程,从而阻止了该线程被耗时的进程阻塞(例如所提到的进程)以上)

The beauty of Javascript and a key reason it works so well for the browser is that it uses the processor thread it runs on in a very clever way that stops the thread from getting blocked by processes that take time (like the ones mentioned above)

许多其他语言(例如Ruby)在多个线程上运行.可以使用Service Worker在javascript中的多个线程上运行进程,但这不在此答案的范围内!

Many other languages, for example Ruby run on more than one thread. It is possible to use service workers to run processes on multiple threads in javascript but that is outside the scope of this answer!

JS事件循环的异步特性允许线程在等待进程完成时离开"并执行其他操作.

The async nature of the JS event loop allows the thread to 'go off' and do something else while it is waiting for a process to finish.

从编程的角度来看,这样做的问题是,如果不等待,依赖于阻塞事件结果的代码中的某些内容可能会由于事件的结果而变得未定义"事件在尝试使用其结果之前完成.在下面使用这段代码

The problem with this from a programming point of view is that it is possible for something in the code that relies on the result of a blocking event to get 'undefined' as a result of the event if it doesn't wait for the event to finish before it tries to use the result of it. Take this piece of code below

let scopedVariable
console.log('the code has started')
setTimeout(() => {
  scopedVariable="I am the result of some async process"
}, 5000);
console.log(scopedVariable)

当代码到达控制台日志时,setTimeout尚未完成.由于setTimeout仅在完成后才设置scopedVariable,因此在我们记录该变量时未定义

When the code reaches the console log, the setTimeout hasn't yet completed. As the setTimeout sets the scopedVariable only when it completes, the variable is undefined when we log it

我们将超时包装在一个Promise中,我们可以等待它的resolve回调(Promise的第一个参数),并且代码将暂停"直到Promise到达resolve回调,然后再继续.

We wrap the timeout in a promise we can await it's resolve callback (first argument of promise) and the code will 'pause' until the promise reaches the resolve callback before continuing.

当我们等待promise并且setTimeout完成时,resolve函数会设置变量,以便在我们控制台日志中它保存promise中的值

When we await the promise and the setTimeout completes, the resolve function sets the variable, so that when we console log it it holds the value from the promise

let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
  setTimeout(() => {
    resolve(scopedVariable="I have resolved")
  }, 5000);
})
const container = async () => {
  const result = await asyncEvent
  console.log(scopedVariable)
}

container()

您可以使用await和.then进行互换

You can use await and .then interchangably

例如,我们可以去

let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
  setTimeout(() => {
    resolve(scopedVariable="I have resolved")
  }, 5000);
})
const container = async () => {
  asyncEvent.then(() => console.log(scopedVariable))
}

container()

再次,代码将在.n处暂停,然后在asyncEvent承诺解决后继续.

once again the code will pause at .then and then continue when the asyncEvent promise has resolved.

实际上,如果我们使用.then,则无需将其包含在异步函数中,因此我们可以像这样重写它

In fact if we use .then we don't need to enclose it in an async function so we can rewrite it like this

let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
  setTimeout(() => {
    resolve(scopedVariable="I have resolved")
  }, 5000);
})

asyncEvent.then(() => console.log(scopedVariable))

.then的伟大之处在于,随附的.catch允许您捕获异步事件引发的任何错误(例如,如果在发生错误时从服务器检索某些内容).对于异步等待,您需要将潜在危险的函数包装在try catch中.

The great thing about .then is that the accompanying .catch allows you to catch any errors thrown by the async event (for example if retrieving something from a server when there is an error). For async await you need to wrap potentially dangerous functions in a try catch.

要使用await,您需要位于一个异步函数内部(因此,上面的异步容器函数). .then不需要这样做,但是.then和.catch链会使您的代码混乱.

In order to use await you need to be inside an async function (hence the async container function above). This is not necessary with .then, but .then and .catch chains can make your code messy.

我希望这会有所帮助!

这篇关于为什么异步总是返回承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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