Hướng dẫn how to make javascript code asynchronous - cách tạo mã javascript không đồng bộ

The author selected the Open Internet/Free Speech Fund to receive a donation as part of the Write for DOnations program.

Introduction

For many programs in JavaScript, code is executed as the developer writes it—line by line. This is called synchronous execution, because the lines are executed one after the other, in the order they were written. However, not every instruction you give to the computer needs to be attended to immediately. For example, if you send a network request, the process executing your code will have to wait for the data to return before it can work on it. In this case, time would be wasted if it did not execute other code while waiting for the network request to be completed. To solve this problem, developers use asynchronous programming, in which lines of code are executed in a different order than the one in which they were written. With asynchronous programming, we can execute other code while we wait for long activities like network requests to finish.

JavaScript code is executed on a single thread within a computer process. Its code is processed synchronously on this thread, with only one instruction run at a time. Therefore, if we were to do a long-running task on this thread, all of the remaining code is blocked until the task is complete. By leveraging JavaScript’s asynchronous programming features, we can offload long-running tasks to a background thread to avoid this problem. When the task is complete, the code we need to process the task’s data is put back on the main single thread.

In this tutorial, you will learn how JavaScript manages asynchronous tasks with help from the Event Loop, which is a JavaScript construct that completes a new task while waiting for another. You will then create a program that uses asynchronous programming to request a list of movies from a Studio Ghibli API and save the data to a CSV file. The asynchronous code will be written in three ways: callbacks, promises, and with the

  1. npm init -y
3/
  1. npm init -y
4 keywords.

Note: As of this writing, asynchronous programming is no longer done using only callbacks, but learning this obsolete method can provide great context as to why the JavaScript community now uses promises. The

  1. npm init -y
3/
  1. npm init -y
4 keywords enable us to use promises in a less verbose way, and are thus the standard way to do asynchronous programming in JavaScript at the time of writing this article.

Prerequisites

  • Node.js installed on your development machine. This tutorial uses version 10.17.0. To install this on macOS or Ubuntu 18.04, follow the steps in How to Install Node.js and Create a Local Development Environment on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.
  • You will also need to be familiar with installing packages in your project. Get up to speed by reading our guide on How To Use Node.js Modules with npm and package.json.
  • It is important that you’re comfortable creating and executing functions in JavaScript before learning how to use them asynchronously. If you need an introduction or refresher, you can read our guide on How To Define Functions in JavaScript

The Event Loop

Let’s begin by studying the internal workings of JavaScript function execution. Understanding how this behaves will allow you to write asynchronous code more deliberately, and will help you with troubleshooting code in the future.

As the JavaScript interpreter executes the code, every function that is called is added to JavaScript’s call stack. The call stack is a stack—a list-like data structure where items can only be added to the top, and removed from the top. Stacks follow the “Last in, first out” or LIFO principle. If you add two items on the stack, the most recently added item is removed first.

Let’s illustrate with an example using the call stack. If JavaScript encounters a function

  1. npm init -y
7 being called, it is added to the call stack. If that function
  1. npm init -y
7 calls another function
  1. npm init -y
9, then
  1. npm init -y
9 is added to the top of the call stack. As JavaScript completes the execution of a function, it is removed from the call stack. Therefore, JavaScript will execute
  1. npm init -y
9 first, remove it from the stack when complete, and then finish the execution of
  1. npm init -y
7 and remove it from the call stack. This is why inner functions are always executed before their outer functions.

When JavaScript encounters an asynchronous operation, like writing to a file, it adds it to a table in its memory. This table stores the operation, the condition for it to be completed, and the function to be called when it’s completed. As the operation completes, JavaScript adds the associated function to the message queue. A queue is another list-like data structure where items can only be added to the bottom but removed from the top. In the message queue, if two or more asynchronous operations are ready for their functions to be executed, the asynchronous operation that was completed first will have its function marked for execution first.

Các chức năng trong hàng đợi tin nhắn đang chờ được thêm vào ngăn xếp cuộc gọi. Vòng lặp sự kiện là một quá trình vĩnh viễn kiểm tra xem ngăn xếp cuộc gọi có trống không. Nếu có, thì mục đầu tiên trong hàng đợi tin nhắn sẽ được chuyển sang ngăn xếp cuộc gọi. JavaScript ưu tiên các chức năng trong hàng đợi tin nhắn qua chức năng gọi nó diễn giải trong mã. Hiệu ứng kết hợp của ngăn xếp cuộc gọi, hàng đợi tin nhắn và vòng lặp sự kiện cho phép mã JavaScript được xử lý trong khi quản lý các hoạt động không đồng bộ.

Bây giờ bạn có một sự hiểu biết cấp cao về vòng lặp sự kiện, bạn đã biết cách mã không đồng bộ bạn viết sẽ được thực thi. Với kiến ​​thức này, bây giờ bạn có thể tạo mã không đồng bộ với ba cách tiếp cận khác nhau: gọi lại, lời hứa và ________ 33/________ 34.

Lập trình không đồng bộ với các cuộc gọi lại

Hàm gọi lại là một hàm được truyền như một đối số cho một hàm khác, và sau đó được thực thi khi hàm khác kết thúc. Chúng tôi sử dụng các cuộc gọi lại để đảm bảo rằng mã chỉ được thực thi sau khi hoàn thành hoạt động không đồng bộ.

Trong một thời gian dài, các cuộc gọi lại là cơ chế phổ biến nhất để viết mã không đồng bộ, nhưng bây giờ chúng phần lớn trở nên lỗi thời vì chúng có thể khiến mã khó hiểu để đọc. Trong bước này, bạn sẽ viết một ví dụ về mã không đồng bộ bằng cách sử dụng các cuộc gọi lại để bạn có thể sử dụng nó như một đường cơ sở để xem hiệu quả tăng của các chiến lược khác.

Có nhiều cách để sử dụng các chức năng gọi lại trong một chức năng khác. Nói chung, họ lấy cấu trúc này:

function asynchronousFunction([ Function Arguments ], [ Callback Function ]) {
    [ Action ]
}

Mặc dù không được JavaScript hoặc Node.js yêu cầu về mặt cú pháp để có chức năng gọi lại là đối số cuối cùng của hàm bên ngoài, nhưng đó là một thực tế phổ biến giúp các cuộc gọi lại dễ dàng hơn để xác định. Nó cũng phổ biến cho các nhà phát triển JavaScript sử dụng chức năng ẩn danh như một cuộc gọi lại. Các hàm ẩn danh là các chức năng được tạo ra mà không có tên. Nó thường dễ đọc hơn nhiều khi một hàm được xác định ở cuối danh sách đối số.

Để chứng minh các cuộc gọi lại, hãy để tạo một mô -đun Node.js ghi danh sách các bộ phim Studio Ghibli vào một tệp. Đầu tiên, hãy tạo một thư mục sẽ lưu trữ tệp JavaScript của chúng tôi và đầu ra của nó:

  1. mkdir ghibliMovies

Sau đó nhập thư mục đó:

  1. cd ghibliMovies

Chúng tôi sẽ bắt đầu bằng cách thực hiện yêu cầu HTTP cho API studio GHIBli, mà chức năng gọi lại của chúng tôi sẽ ghi lại kết quả. Để làm điều này, chúng tôi sẽ cài đặt một thư viện cho phép chúng tôi truy cập dữ liệu của phản hồi HTTP trong cuộc gọi lại.

Trong thiết bị đầu cuối của bạn, khởi tạo NPM để chúng tôi có thể có một tham chiếu cho các gói của chúng tôi sau:

  1. npm init -y

Sau đó, cài đặt thư viện

  1. npm i request --save
5:

  1. npm i request --save

Bây giờ hãy mở một tệp mới có tên

  1. npm i request --save
6 trong trình soạn thảo văn bản như
  1. npm i request --save
7:

  1. nano callbackMovies.js

Trong trình soạn thảo văn bản của bạn, nhập mã sau. Hãy bắt đầu bằng cách gửi yêu cầu HTTP với mô -đun

  1. npm i request --save
5:

callbackMovies.js

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');

Trong dòng đầu tiên, chúng tôi tải mô -đun

  1. npm i request --save
5 được cài đặt qua NPM. Mô -đun trả về một hàm có thể thực hiện các yêu cầu HTTP; Sau đó, chúng tôi lưu chức năng đó trong hằng số
  1. npm i request --save
5.

Sau đó, chúng tôi thực hiện yêu cầu HTTP bằng hàm

  1. nano callbackMovies.js
1. Bây giờ, hãy để in dữ liệu từ yêu cầu HTTP vào bảng điều khiển bằng cách thêm các thay đổi được tô sáng:

callbackMovies.js

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});

Khi chúng tôi sử dụng hàm

  1. nano callbackMovies.js
1, chúng tôi cung cấp cho nó hai tham số:

  • URL của trang web chúng tôi đang cố gắng yêu cầu
  • Một chức năng gọi lại xử lý bất kỳ lỗi hoặc phản hồi thành công sau khi yêu cầu hoàn tất

Hàm gọi lại của chúng tôi có ba đối số:

  1. nano callbackMovies.js
3,
  1. nano callbackMovies.js
4 và
  1. nano callbackMovies.js
5. Khi yêu cầu HTTP hoàn tất, các đối số được tự động đưa ra các giá trị tùy thuộc vào kết quả. Nếu yêu cầu không gửi, thì
  1. nano callbackMovies.js
3 sẽ chứa một đối tượng, nhưng
  1. nano callbackMovies.js
4 và
  1. nano callbackMovies.js
5 sẽ là
  1. nano callbackMovies.js
9. Nếu nó thực hiện yêu cầu thành công, thì phản hồi HTTP được lưu trữ trong
  1. nano callbackMovies.js
4. Nếu phản hồi HTTP của chúng tôi trả về dữ liệu (trong ví dụ này, chúng tôi sẽ nhận được JSON) thì dữ liệu được đặt trong
  1. nano callbackMovies.js
5.

Chức năng gọi lại của chúng tôi trước tiên kiểm tra xem chúng tôi có nhận được lỗi không. Trước tiên, nó thực hành tốt nhất để kiểm tra các lỗi trong cuộc gọi lại trước tiên để thực hiện cuộc gọi lại won tiếp tục với dữ liệu bị thiếu. Trong trường hợp này, chúng tôi đăng nhập lỗi và thực thi chức năng. Sau đó chúng tôi kiểm tra mã trạng thái của phản hồi. Máy chủ của chúng tôi có thể không phải lúc nào cũng có sẵn và API có thể thay đổi khiến các yêu cầu hợp lý trở nên không chính xác. Bằng cách kiểm tra xem mã trạng thái là

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
2, điều đó có nghĩa là yêu cầu là OK OK, chúng tôi có thể tin tưởng rằng phản hồi của chúng tôi là những gì chúng tôi mong đợi.

Cuối cùng, chúng tôi phân tích cơ thể phản hồi cho một

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
3 và lặp qua mỗi bộ phim để đăng nhập tên và năm phát hành của nó.

Sau khi lưu và bỏ tệp, hãy chạy tập lệnh này với:

  1. node callbackMovies.js

Bạn sẽ nhận được đầu ra sau:

Output

Castle in the Sky, 1986 Grave of the Fireflies, 1988 My Neighbor Totoro, 1988 Kiki's Delivery Service, 1989 Only Yesterday, 1991 Porco Rosso, 1992 Pom Poko, 1994 Whisper of the Heart, 1995 Princess Mononoke, 1997 My Neighbors the Yamadas, 1999 Spirited Away, 2001 The Cat Returns, 2002 Howl's Moving Castle, 2004 Tales from Earthsea, 2006 Ponyo, 2008 Arrietty, 2010 From Up on Poppy Hill, 2011 The Wind Rises, 2013 The Tale of the Princess Kaguya, 2013 When Marnie Was There, 2014

Chúng tôi đã nhận được thành công một danh sách các bộ phim Studio Ghibli với năm chúng được phát hành. Bây giờ, hãy để hoàn thành chương trình này bằng cách viết danh sách phim mà chúng tôi hiện đang đăng nhập vào một tệp.

Cập nhật tệp

  1. npm i request --save
6 trong trình soạn thảo văn bản của bạn để bao gồm mã được tô sáng sau, tạo tệp CSV với dữ liệu phim của chúng tôi:

callbackMovies.js

  1. mkdir ghibliMovies
0

Lưu ý các thay đổi được tô sáng, chúng tôi thấy rằng chúng tôi nhập mô -đun

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
5. Mô -đun này là tiêu chuẩn trong tất cả các cài đặt Node.js và nó chứa phương thức
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6 có thể ghi không đồng bộ vào một tệp.

Thay vì đăng nhập dữ liệu vào bảng điều khiển, bây giờ chúng tôi thêm nó vào một biến chuỗi

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
7. Sau đó, chúng tôi sử dụng
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6 để lưu nội dung của
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
7 vào một tệp mới. Cuối cùng, chúng tôi cung cấp một cuộc gọi lại cho hàm
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6, có một đối số:
  1. nano callbackMovies.js
3. Điều này cho phép chúng tôi xử lý các trường hợp mà chúng tôi không thể ghi vào một tệp, ví dụ như khi người dùng chúng tôi đang chạy quy trình
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
3 trên không có những quyền đó.

Lưu tệp và chạy chương trình Node.js này một lần nữa với:

  1. node callbackMovies.js

Trong thư mục

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
4 của bạn, bạn sẽ thấy
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
0, có nội dung sau:

callbackMovies.csv

  1. mkdir ghibliMovies
2

Điều quan trọng cần lưu ý là chúng tôi ghi vào tệp CSV của mình trong cuộc gọi lại của yêu cầu HTTP. Khi mã nằm trong hàm gọi lại, nó sẽ chỉ ghi vào tệp sau khi yêu cầu HTTP hoàn tất. Nếu chúng tôi muốn liên lạc với cơ sở dữ liệu sau khi chúng tôi viết tệp CSV của mình, chúng tôi sẽ tạo ra một chức năng không đồng bộ khác sẽ được gọi trong cuộc gọi lại của

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6. Chúng ta càng có mã không đồng bộ, các chức năng gọi lại phải được lồng nhau.

Hãy để tưởng tượng rằng chúng tôi muốn thực hiện năm hoạt động không đồng bộ, mỗi người chỉ có thể chạy khi một hoạt động khác hoàn thành. Nếu chúng ta viết mã này, chúng ta sẽ có một cái gì đó như thế này:

  1. mkdir ghibliMovies
3

Khi các cuộc gọi lại lồng nhau có nhiều dòng mã để thực thi, chúng trở nên phức tạp hơn và không thể đọc được. Khi dự án JavaScript của bạn phát triển về kích thước và độ phức tạp, hiệu ứng này sẽ trở nên rõ rệt hơn, cho đến khi cuối cùng nó không thể quản lý được. Bởi vì điều này, các nhà phát triển không còn sử dụng các cuộc gọi lại để xử lý các hoạt động không đồng bộ. Để cải thiện cú pháp của mã không đồng bộ của chúng tôi, chúng tôi có thể sử dụng lời hứa thay thế.

Sử dụng những lời hứa cho lập trình không đồng bộ ngắn gọn

Một lời hứa là một đối tượng JavaScript sẽ trả về một giá trị tại một thời điểm nào đó trong tương lai. Các hàm không đồng bộ có thể trả về các đối tượng hứa hẹn thay vì các giá trị cụ thể. Nếu chúng ta nhận được một giá trị trong tương lai, chúng ta nói rằng lời hứa đã được thực hiện. Nếu chúng ta gặp lỗi trong tương lai, chúng ta nói rằng lời hứa đã bị từ chối. Nếu không, lời hứa vẫn đang được thực hiện trong tình trạng đang chờ xử lý.

Lời hứa thường có hình thức sau:

  1. mkdir ghibliMovies
4

Như được hiển thị trong mẫu này, hứa hẹn cũng sử dụng các chức năng gọi lại. Chúng tôi có chức năng gọi lại cho phương thức

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7, được thực hiện khi một lời hứa được thực hiện. Chúng tôi cũng có chức năng gọi lại cho phương thức
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
8 để xử lý bất kỳ lỗi nào xảy ra trong khi lời hứa đang được thực thi.

Hãy để có được trải nghiệm trực tiếp với những lời hứa bằng cách viết lại chương trình Studio Ghibli của chúng tôi để sử dụng lời hứa thay thế.

Axios là một ứng dụng khách HTTP dựa trên lời hứa cho JavaScript, vì vậy hãy để Lôi tiếp tục và cài đặt nó:

  1. mkdir ghibliMovies
5

Bây giờ, với trình soạn thảo văn bản của bạn, hãy tạo một tệp mới

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
9:

  1. mkdir ghibliMovies
6

Chương trình của chúng tôi sẽ thực hiện yêu cầu HTTP với

  1. node callbackMovies.js
0 và sau đó sử dụng phiên bản
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
5 dựa trên lời hứa đặc biệt để lưu vào tệp CSV mới.

Nhập mã này vào

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
9 để chúng tôi có thể tải Axios và gửi yêu cầu HTTP đến API phim:

promiseMovies.js

  1. mkdir ghibliMovies
7

Trong dòng đầu tiên, chúng tôi tải mô -đun

  1. node callbackMovies.js
0, lưu trữ hàm được trả về trong một hằng số gọi là
  1. node callbackMovies.js
0. Sau đó, chúng tôi sử dụng phương thức
  1. node callbackMovies.js
5 để gửi yêu cầu HTTP đến API.

Phương pháp

  1. node callbackMovies.js
5 trả về một lời hứa. Hãy để chuỗi hứa hẹn để chúng ta có thể in danh sách các bộ phim Ghibli vào bảng điều khiển:

promiseMovies.js

  1. mkdir ghibliMovies
8

Hãy để phá vỡ những gì mà xảy ra. Sau khi thực hiện yêu cầu HTTP nhận được

  1. node callbackMovies.js
5, chúng tôi sử dụng hàm
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7, chỉ được thực hiện khi lời hứa được thực hiện. Trong trường hợp này, chúng tôi in các bộ phim lên màn hình như chúng tôi đã làm trong ví dụ gọi lại.

Để cải thiện chương trình này, hãy thêm mã được tô sáng để ghi dữ liệu HTTP vào tệp:

promiseMovies.js

  1. mkdir ghibliMovies
9

Chúng tôi cũng nhập mô -đun

const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
5 một lần nữa. Lưu ý làm thế nào sau khi nhập
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
5, chúng tôi có

Output

Castle in the Sky, 1986 Grave of the Fireflies, 1988 My Neighbor Totoro, 1988 Kiki's Delivery Service, 1989 Only Yesterday, 1991 Porco Rosso, 1992 Pom Poko, 1994 Whisper of the Heart, 1995 Princess Mononoke, 1997 My Neighbors the Yamadas, 1999 Spirited Away, 2001 The Cat Returns, 2002 Howl's Moving Castle, 2004 Tales from Earthsea, 2006 Ponyo, 2008 Arrietty, 2010 From Up on Poppy Hill, 2011 The Wind Rises, 2013 The Tale of the Princess Kaguya, 2013 When Marnie Was There, 2014
1. Node.js bao gồm một phiên bản dựa trên lời hứa của thư viện ____65 dựa trên gọi lại, vì vậy khả năng tương thích ngược không bị phá vỡ trong các dự án cũ.

Hàm

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7 đầu tiên xử lý yêu cầu HTTP hiện gọi

Output

Castle in the Sky, 1986 Grave of the Fireflies, 1988 My Neighbor Totoro, 1988 Kiki's Delivery Service, 1989 Only Yesterday, 1991 Porco Rosso, 1992 Pom Poko, 1994 Whisper of the Heart, 1995 Princess Mononoke, 1997 My Neighbors the Yamadas, 1999 Spirited Away, 2001 The Cat Returns, 2002 Howl's Moving Castle, 2004 Tales from Earthsea, 2006 Ponyo, 2008 Arrietty, 2010 From Up on Poppy Hill, 2011 The Wind Rises, 2013 The Tale of the Princess Kaguya, 2013 When Marnie Was There, 2014
4 thay vì in vào bảng điều khiển. Vì chúng tôi đã nhập phiên bản
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
5 dựa trên lời hứa, chức năng
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6 của chúng tôi trả về một lời hứa khác. Như vậy, chúng tôi nối thêm một chức năng
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7 khác khi lời hứa
const request = require('request');

request('https://ghibliapi.herokuapp.com/films');
6 được thực hiện.

Một lời hứa có thể trả lại một lời hứa mới, cho phép chúng tôi thực hiện những lời hứa hết lần này đến lần khác. Điều này mở đường cho chúng tôi thực hiện nhiều hoạt động không đồng bộ. Điều này được gọi là chuỗi hứa hẹn, và nó tương tự như các cuộc gọi lại làm tổ.

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7 thứ hai chỉ được gọi sau khi chúng tôi ghi thành công vào tệp.

Lưu ý: Trong ví dụ này, chúng tôi đã không kiểm tra mã trạng thái HTTP như chúng tôi đã làm trong ví dụ gọi lại. Theo mặc định,

  1. node callbackMovies.js
0 không thực hiện lời hứa của mình nếu nó nhận được mã trạng thái cho biết lỗi. Như vậy, chúng tôi không còn cần phải xác nhận nó. In this example, we did not check for the HTTP status code like we did in the callback example. By default,
  1. node callbackMovies.js
0 does not fulfil its promise if it gets a status code indicating an error. As such, we no longer need to validate it.

Để hoàn thành chương trình này, chuỗi lời hứa với chức năng

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
8 vì nó được tô sáng sau:

promiseMovies.js

  1. cd ghibliMovies
0

Nếu bất kỳ lời hứa nào không được thực hiện trong chuỗi lời hứa, JavaScript sẽ tự động chuyển đến hàm

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
8 nếu nó được xác định. Đó là lý do tại sao chúng tôi chỉ có một mệnh đề
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
8 mặc dù chúng tôi có hai hoạt động không đồng bộ.

Hãy để xác nhận rằng chương trình của chúng tôi tạo ra cùng một đầu ra bằng cách chạy:

  1. cd ghibliMovies
1

Trong thư mục

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
4 của bạn, bạn sẽ thấy tệp
  1. mkdir ghibliMovies
05 chứa:

promiseMovies.csv

  1. mkdir ghibliMovies
2

Với lời hứa, chúng ta có thể viết mã súc tích hơn nhiều so với chỉ sử dụng các cuộc gọi lại. Chuỗi lời hứa của các cuộc gọi lại là một lựa chọn sạch hơn so với các cuộc gọi lại làm tổ. Tuy nhiên, khi chúng tôi thực hiện các cuộc gọi không đồng bộ hơn, chuỗi hứa hẹn của chúng tôi trở nên dài hơn và khó duy trì hơn.

Sự xác định của các cuộc gọi lại và lời hứa đến từ sự cần thiết phải tạo ra các chức năng khi chúng ta có kết quả của một nhiệm vụ không đồng bộ. Một trải nghiệm tốt hơn là chờ đợi một kết quả không đồng bộ và đặt nó vào một biến bên ngoài chức năng. Bằng cách đó, chúng ta có thể sử dụng các kết quả trong các biến mà không phải tạo chức năng. Chúng ta có thể đạt được điều này với các từ khóa

  1. npm init -y
3 và
  1. npm init -y
4.

Viết JavaScript bằng ________ 33/________ 34

Các từ khóa ____ 33/________ 34 cung cấp một cú pháp thay thế khi làm việc với lời hứa. Thay vì có kết quả của một lời hứa có sẵn trong phương thức

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7, kết quả được trả về dưới dạng giá trị như trong bất kỳ chức năng nào khác. Chúng tôi xác định một hàm với từ khóa
  1. npm init -y
3 để nói với JavaScript rằng nó có một hàm không đồng bộ trả về một lời hứa. Chúng tôi sử dụng từ khóa
  1. npm init -y
4 để nói với JavaScript để trả về kết quả của lời hứa thay vì trả lại lời hứa khi nó hoàn thành.

Nói chung, ________ 33/________ 34 Cách sử dụng trông như thế này:

  1. cd ghibliMovies
3

Hãy cùng xem cách sử dụng ________ 33/________ 34 có thể cải thiện chương trình Studio Ghibli của chúng tôi. Sử dụng trình soạn thảo văn bản của bạn để tạo và mở tệp mới

  1. mkdir ghibliMovies
19:

  1. cd ghibliMovies
4

Trong tệp JavaScript mới mở của bạn, hãy để bắt đầu bằng cách nhập các mô -đun tương tự mà chúng tôi đã sử dụng trong ví dụ hứa hẹn của chúng tôi:

asyncAwaitMovies.js

  1. cd ghibliMovies
5

Nhập khẩu giống như

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
9 vì ________ 33/________ 34 sử dụng lời hứa.

Bây giờ chúng tôi sử dụng từ khóa

  1. npm init -y
3 để tạo chức năng với mã không đồng bộ của chúng tôi:

asyncAwaitMovies.js

  1. cd ghibliMovies
6

Chúng tôi tạo một hàm mới gọi là

  1. mkdir ghibliMovies
24 nhưng chúng tôi bao gồm
  1. npm init -y
3 khi bắt đầu định nghĩa của nó. Điều này rất quan trọng vì chúng tôi chỉ có thể sử dụng từ khóa
  1. npm init -y
4 trong một hàm không đồng bộ.

Sử dụng từ khóa

  1. npm init -y
4 để thực hiện yêu cầu HTTP nhận danh sách các bộ phim từ API GHIBLI:

asyncawaitmovies.js

  1. cd ghibliMovies
7

Trong chức năng

  1. mkdir ghibliMovies
24 của chúng tôi, chúng tôi thực hiện yêu cầu HTTP với
  1. node callbackMovies.js
5 như trước. Lần này, chúng tôi không có chuỗi nó với chức năng
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
7. Thay vào đó, chúng tôi thêm
  1. npm init -y
4 trước khi nó được gọi. Khi JavaScript nhìn thấy
  1. npm init -y
4, nó sẽ chỉ thực thi mã còn lại của hàm sau khi
  1. node callbackMovies.js
5 hoàn thành thực thi và đặt biến
  1. nano callbackMovies.js
4. Mã khác lưu dữ liệu phim để chúng tôi có thể ghi vào một tệp.

Hãy để viết dữ liệu phim vào một tệp:

asyncAwaitMovies.js

  1. cd ghibliMovies
8

Chúng tôi cũng sử dụng từ khóa

  1. npm init -y
4 khi chúng tôi ghi vào tệp với

Output

Castle in the Sky, 1986 Grave of the Fireflies, 1988 My Neighbor Totoro, 1988 Kiki's Delivery Service, 1989 Only Yesterday, 1991 Porco Rosso, 1992 Pom Poko, 1994 Whisper of the Heart, 1995 Princess Mononoke, 1997 My Neighbors the Yamadas, 1999 Spirited Away, 2001 The Cat Returns, 2002 Howl's Moving Castle, 2004 Tales from Earthsea, 2006 Ponyo, 2008 Arrietty, 2010 From Up on Poppy Hill, 2011 The Wind Rises, 2013 The Tale of the Princess Kaguya, 2013 When Marnie Was There, 2014
4.

Để hoàn thành chức năng này, chúng ta cần bắt lỗi lời hứa của chúng ta có thể ném. Hãy cùng làm điều này bằng cách gói gọn mã của chúng tôi trong khối ____ 137/________ 138:

asyncAwaitMovies.js

  1. cd ghibliMovies
9

Vì những lời hứa có thể thất bại, chúng tôi mã hóa mã không đồng bộ của chúng tôi với mệnh đề ________ 137/________ 138. Điều này sẽ thu được bất kỳ lỗi nào được ném khi yêu cầu HTTP hoặc hoạt động viết tệp không thành công.

Cuối cùng, hãy để Lôi gọi chức năng không đồng bộ của chúng tôi

  1. mkdir ghibliMovies
24 để nó được thực hiện khi chúng tôi chạy chương trình với
const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
3

asyncAwaitMovies.js

  1. npm init -y
0

Nhìn thoáng qua, điều này trông giống như một khối mã JavaScript đồng bộ điển hình. Nó có ít chức năng hơn được truyền xung quanh, trông hơi gọn gàng hơn. Các tinh chỉnh nhỏ này tạo ra mã không đồng bộ với ________ 33/________ 34 dễ bảo trì hơn.

Kiểm tra lần lặp này của chương trình của chúng tôi bằng cách nhập bài này vào thiết bị đầu cuối của bạn:

  1. npm init -y
1

Trong thư mục

const request = require('request');

request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
    if (error) {
        console.error(`Could not send request to API: ${error.message}`);
        return;
    }

    if (response.statusCode != 200) {
        console.error(`Expected status code 200 but received ${response.statusCode}.`);
        return;
    }

    console.log('Processing our list of movies');
    movies = JSON.parse(body);
    movies.forEach(movie => {
        console.log(`${movie['title']}, ${movie['release_date']}`);
    });
});
4 của bạn, một tệp
  1. mkdir ghibliMovies
46 mới sẽ được tạo với các nội dung sau:

asyncAwaitMovies.csv

  1. mkdir ghibliMovies
2

Bây giờ bạn đã sử dụng các tính năng JavaScript ____ 33/________ 34 để quản lý mã không đồng bộ.

Sự kết luận

Trong hướng dẫn này, bạn đã tìm hiểu cách JavaScript xử lý các chức năng thực thi và quản lý các hoạt động không đồng bộ với vòng lặp sự kiện. Sau đó, bạn đã viết các chương trình tạo tệp CSV sau khi thực hiện yêu cầu HTTP cho dữ liệu phim bằng các kỹ thuật lập trình không đồng bộ khác nhau. Đầu tiên, bạn đã sử dụng phương pháp dựa trên cuộc gọi lại lỗi thời. Sau đó, bạn đã sử dụng những lời hứa, và cuối cùng ____ 33/________ 34 để làm cho cú pháp hứa hẹn cô đọng hơn.

Với sự hiểu biết của bạn về mã không đồng bộ với Node.js, giờ đây bạn có thể phát triển các chương trình được hưởng lợi từ lập trình không đồng bộ, giống như các chương trình dựa vào các cuộc gọi API. Hãy xem danh sách API công khai này. Để sử dụng chúng, bạn sẽ phải thực hiện các yêu cầu HTTP không đồng bộ như chúng tôi đã làm trong hướng dẫn này. Để nghiên cứu thêm, hãy thử xây dựng một ứng dụng sử dụng các API này để thực hành các kỹ thuật bạn đã học ở đây.

Làm thế nào chúng ta có thể làm cho JavaScript không đồng bộ?

JavaScript không đồng bộ..
Hàm MyDisplayer (Something) {Document. ....
setTimeout (myFunction, 3000); Hàm myFunction () {....
setTimeout (function () {myFunction ("Tôi yêu bạn !!!");}, 3000); Hàm myFunction (value) {....
setInterval (myfunction, 1000); Hàm myFunction () {....
Đang chờ một tệp: Hàm MyDisplayer (một số) {.

JS có thể không đồng bộ không?

JavaScript là một ngôn ngữ lập trình đồng thời, không chặn, không đồng bộ, không đồng thời với rất nhiều sự linh hoạt. with lots of flexibility.

JavaScript xử lý mã không đồng bộ như thế nào?

JavaScript không đồng bộ: Để xử lý dữ liệu không đồng bộ, chúng tôi sử dụng lời hứa hoặc cuộc gọi lại giúp người dùng dễ dàng tìm nạp phản hồi hoặc dữ liệu từ API một cách dễ dàng.Sau khi hiểu được những điều cơ bản của Stack Call, một số khái niệm kỹ thuật khác tồn tại như Loop sự kiện, API Web và hàng đợi tin nhắn.use promises or callbacks which helps users easily fetch responses or data from the API with ease. After understanding the basics of Call Stack, some more technical concepts exist like Event Loop, Web API, and Message Queue.

Tại sao JavaScript không đồng bộ?

JavaScript luôn đồng bộ và một luồng đơn.JavaScript chỉ không đồng bộ theo nghĩa mà nó có thể tạo ra, ví dụ, các cuộc gọi Ajax.Cuộc gọi AJAX sẽ ngừng thực thi và mã khác sẽ có thể thực thi cho đến khi cuộc gọi trả về (thành công hoặc cách khác), tại thời điểm đó, cuộc gọi lại sẽ chạy đồng bộ.JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. The Ajax call will stop executing and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously.