了解JavaScript中的异步/等待模式

mst*_*son 3 javascript async-await

我对JavaScript编程比较陌生,所以回调一直给我带来麻烦.我正在使用支持ES7(Meteor)的"async/await"语法的框架,但是我很难理解如何实现调用其他函数的异步函数.

我想做的事:用户输入URL,从URL获取数据,处理数据并将其放入数据库.我希望以非阻塞方式进行此操作,以便用户可以在此过程发生时继续使用该应用程序.

伪代码:

async function foo(URL) {
    try {
        //using request-promise npm package to make the request
        const data = await makeRequestPromise(URL) 
        const parsedData = await myParsingFunciton(data);
        MyDB.insert({
            parsedData,
        });
    catch (err) {
        console.log(err);
    }
Run Code Online (Sandbox Code Playgroud)

所以我有几个问题:

  • 在这个异步函数范围内发生的任何事情都是非阻塞的吗?
  • 如果是这样,我可以使用一系列同步函数,因为我无论如何都无法解析数据吗?
  • 如果我尝试等待未定义为异步的函数(例如myParsingFunction)会发生什么?我的研究似乎暗示该函数被迫返回一个承诺,但我不确定我将如何确定.在代码中这样做不会返回错误,但JavaScript似乎出乎意料地容忍返回方面的怪异.

我想补充一点,我的函数可以工作,而且事情会进入数据库,但我不知道如何测试它是否实际上是非阻塞的.

T.J*_*der 9

在这个异步函数范围内发生的任何事情都是非阻塞的吗?

它是非阻塞的,因为调用foo不会在完成所有工作之前停止线程,因为它foo是一个调用至少一个其他异步函数的异步函数.浏览器上只有一个主要UI线程(NodeJS中有一个线程),因此除非您在浏览器中使用Web worker,否则异步代码将在某个时刻占用该线程(例如,阻塞).但是你调用的异步函数foo不会阻塞内部的线程foo; 相反,foo在完成所有异步工作后,最终会在幕后返回一个承诺.(这就是为什么它是异步功能.)

如果是这样,我可以使用一系列同步函数,因为我无论如何都无法解析数据吗?

不太关注这个问题.你的代码看起来很好.它看起来是同步的,但它不是,假设你调用的一个或多个函数是异步的.

如果我尝试等待未定义为异步的函数(例如myParsingFunction)会发生什么?

它使您对该函数的调用异步(即使该函数不是),但此后解析会尽快发生; 分辨率值是函数返回的值.你可以看到这个快速实验的实际应用:

// `foo` is an asynchronous function, and so calling it returns a promise
async function foo() {
  // We haven't awaited anything yet, so this is run synchronously when we
  // call `foo`
  console.log("A");
  // `Math.random` is, of course, a synchronous function; but we *call* it
  // asynchronously since we've used `await`
  let data = await Math.random();
  // Which means this line doesn't run until later, after `foo` has already
  // returned its promise
  console.log("B");
}

// When we call `foo`, the synchronous part runs first and it returns its
// promise (which we're not using)
foo();
// And then this line runs, BEFORE the asynchronous part of `foo` can run
console.log("C");

// ...and so we see A, C, B; without the `await` on the call to
// `Math.random`, we'd see A, B, C
Run Code Online (Sandbox Code Playgroud)


它可能(或可能不是)有用来记住async/ await纯粹是用于与promises交互的语法糖.async表示函数返回一个promise.await意味着您正在等待(异步)进行承诺解析.

例如:

async function foo() {
    return 42;
}
Run Code Online (Sandbox Code Playgroud)

是糖

function foo() {
    return new Promise(resolve => {
        resolve(42);
    });
}
Run Code Online (Sandbox Code Playgroud)

和糖

let data = await something();
// ...do somthing...
Run Code Online (Sandbox Code Playgroud)

something().then(data => {
    // ...do something...
});
Run Code Online (Sandbox Code Playgroud)

抛开一些细节.