繁体   English   中英

在 JavaScript 中使用 Promise 和 Async/Await

[英]Using Promises and Async/Await in JavaScript

我在 JavaScript 中阅读了一些关于 Promises 和async / await的文章来理解它的观点,但还没有完全理解它; 所以,我会在这里解释一个例子,希望你帮助我理解这个机制。 以下代码在 NestJS 中。

这是我的auth.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(UserRepository)
    private userRepository: UserRepository
  ) {}

  createUser(): void {
    this.userRepository.createUser();

    console.log('Here I want to do some other works simultaneously while this.userRepository.createUser() is also processing');
  }
}

这是我的user.repository.ts

import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';

@EntityRepository(User)
export class UserRepository extends Repository<User> {
  async createUser(): Promise<void> {
    await this.makeUser();
  }

  async makeUser(): Promise<void> {
    return new Promise((resolve, reject) => {
      // Simulating making a user which will take some time
      let x = 1;
      for (let i = 0; i < 1000000000; i++) {
        x++;
      }

      console.log('User Created');

      resolve();
    });
  }
}

根据上面的代码和到目前为止我所学到的,我期望的是console.log('Here I want to do some other works simultaneously...')行在this.userRepository.createUser() ,但这不会发生,我首先记录了"User Created" ,然后我得到"Here I want to do some other works simultaneously..."

我哪里错了?

问题是您的makeUser() function 实际上并不是异步的。 仅仅因为它返回 promise 并不意味着它执行的工作不会阻塞不等待其完成的代码路径。 JavaScript 仍然是单线程的,在for循环完成之前,没有其他代码能够执行。

一个更合理的模拟实现可能如下所示:

  async makeUser(): Promise<void> {
    return new Promise((resolve, reject) => {
      // Simulating making a user which will take some time
      setTimeout(() => {
        console.log('User Created');

        resolve();
      }, 1000);
    });
  }

请注意, setTimeout()是真正异步 function 的示例:它安排 function 稍后调用,而不会阻塞线程。 另请注意,由于 JavaScript 是单线程的,因此setTimeout()调度的回调 function 将在所有其他代码路径执行完毕后才会执行,因此这是双向的,以下不会导致两个同时执行的代码路径:

 setTimeout(() => { console.log('scheduled'); }, 50); let later = Date.now() + 100; while (later > Date.now()) {} console.log('done');

在这种情况下, scheduled永远不会在done之前出现,它总是会在之后打印。

使用Workers在 JavaScript 中可以实现多线程。

但是,由于 JavaScript 是单线程的,因此诸如 Workers 之类的东西是由您运行 JavaScript 的环境(NodeJS 或浏览器)提供的。制作 http 是很好的例子。 它们不是 JavaScript 本身的一部分,而是由浏览器或 NodeJS 实现。

有关异步工作的示例,请在一些JS 操场上运行以下代码段:

(async function () {
 function makeRequest() {
    return fetch('https://jsonplaceholder.typicode.com/todos/1').then(response => response.json()).then(json => console.log("Http request complete", json))
  }
  const promise = makeRequest()
  console.log('Here I want to do work while the http request is made')
  await promise
  console.log("Here I want to continue after http request is complete")
})();

如果你想了解更多我推荐这个谈话和这篇文章

我哪里错了?

JavaScript 是单线程的,所以任何时候只能运行一段代码。

有一些例外,例如 HTTP 请求(这些请求被移交给线程)。

异步并不意味着“并行”。

同步执行是有序的:一件接一件的事情发生:

  1. 做任务 1
  2. 处理任务 1 的结果
  3. 执行任务 2
  4. 处理任务 2 的结果

异步执行没有顺序(因此是异步的):

  1. 做任务 1
  2. 执行任务 2
  3. 处理任务 1 的结果
  4. 处理任务 2 的结果

您可能想知道“在您的异步示例中,Do Task 1 和 Do Task 2 是并行执行的”。 这不是真的,异步性与并行性无关,它与“无序”执行有关。

异步性背后的力量在于,如果正确实施,允许多个代码段“乱序”运行,给人的印象是它们是并行运行的。 *

*这并不是说异步代码不允许并行。 实际上是异步代码允许并行处理发生的情况,因为结果是在它准备好时处理的。 当然,如果你只有一个线程,那么异步根本不会给你带来任何真正的好处。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM