authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
穆罕默德·阿马尔·伊利亚斯
验证专家 在工程
11 的经验

Muhammad is a full-stack developer with more than a decade of experience delivering web and mobile applications for various companies, 包括观测仪的, Microblink, 和Resulta. He has JavaScript expertise ranging across Node.js,下一个.js, 反应, 反应 Native, and headless WordPress solutions.

以前的角色

高级WordPress开发人员

以前在

观测仪的
分享

作为开发者, I naturally want my software to be reliable and responsive. In the early days of my career, feedback on my applications was mixed. 一些应用获得了很高的评价, but reviews were inconsistent on other apps because they would intermittently stop responding midsession—and we all know how little patience end users have for poor program responsiveness.

The underlying issue was that the apps were coded using purely synchronous JavaScript. Since JavaScript offers (seemingly) asynchronous functions, it’s easy to miss the fact that JavaScript’s runtime itself is synchronous by default, and this is a potential pitfall for developers. My curiosity drove me to investigate this programmatic puzzle.

The Problem: JavaScript Synchronous Blocking

I started my exploration by observing the way that regular, 同步调用工作, focusing my efforts on call stacks—last in, first out (LIFO) programming 结构.

All call stacks function alike, regardless of the language: We (add) function calls to the stack and then 流行 如有需要,可将其移除.

让我们考虑一个简短的例子:

函数乘法(a, b) {
    返回a * b;
}

函数平方(n) {
    返回乘(n, n);
}

函数printSquare(n) {
    const 广场dNum = 广场(n);
    控制台.日志(广场dNum);
}

printSquare (4);

In our example, the outermost function, printSquare,叫。 广场 函数,该函数反过来调用 . Functions are added to our call stack in the order they are encountered. As each method is completed, it is removed from the end of the call stack (i.e., 会首先被移除).

A column labeled call stack containing cells that are labeled (from bottom to top): printSquare(4), 广场(4), 和繁殖(4, 4).
JavaScript调用栈示例

Since the call stack is synchronous, when one or more of these functions takes significant time to complete, 剩余的任务被阻塞. Our program becomes unresponsive—at least temporarily—and resumes only when the blocked function is completed.

Common function calls resulting in these program delays include:

  • A loop with a high iteration count (e.g.(从1到1万亿).
  • A network request to an external web server.
  • An event that waits for a timer to complete.
  • 图像处理.

在web浏览器中为最终用户提供, synchronous call blockages result in an inability to interact with page 元素s. 对于开发者来说, these stuck calls make the development 控制台 inaccessible and take away the ability to examine detailed debugging information.

The Solution: 异步 JavaScript Functionality

异步 coding is a programming technique in which, 在调用函数之后, the remainder of our code can run without having to wait for the initial function to return. When an asynchronous task completes, the JavaScript runtime passes the result to a function of our choosing. This method eliminates obstacles for our end users and developers.

JavaScript实现 异步功能 via a few key architectural components:

An animation showing the interaction and flow between the JavaScript call stack, 浏览器API, and task queue that support asynchronous functions.
JavaScript的异步流

Anything that needs to run asynchronously (e.g., a timer or external API call) is sent to the runtime engine’s 浏览器API (web API). The 浏览器API spawns a single execution thread per operation routed its way.

Each 异步JavaScript function call sent to the 浏览器API has a corresponding promise that allows handler code to be triggered when the function completes (either successfully or unsuccessfully). 当 function completes—regardless of whether it returns a value—its return fulfills its associated promise, and the function moves from the 浏览器API into JavaScript’s task queue.

The key player in JavaScript’s asynchronous processing is its 事件循环. The 事件循环 continuously checks if the call stack and task queue are empty, and coordinates when those completed asynchronous calls should be 推ed back onto the main call stack.

现在让我们检查一下JavaScript setTimeout method to see JavaScript’s asynchronous method handling in action:

函数a() {
    b();
}

函数b() {
    setTimeout(() => {
        控制台.日志(“5秒后”);
    }, 5000);
}

函数c() {
    控制台.日志(“Hello World”);
}

a();
c();

An animation showing a detailed flow from JavaScript’s call stack into the 浏览器API and task queue for the preceding code example.
浏览器API如何处理 setTimeout的函数

让我们看一下代码:

  1. a 转到调用堆栈.
  2. b’s setTimeout invocation is moved to the 浏览器API call stack.
  3. c 转到调用堆栈.
  4. c’s 控制台.日志 将调用推入调用堆栈.
  5. setTimeout method completes, it is moved from the 浏览器API to the task queue.
  6. Any functions within the call stack process to completion.
  7. 当 call stack empties, the 事件循环 moves the setTimeout’s function from the task queue back into the call stack.

软件工程师 can expand their development capabilities through the application of these JavaScript asynchronous methods. Now that we have seen how asynchronous methods within the JavaScript runtime are handled, I’ll demonstrate their applicability with a short example.

Real-world Applications: A Chatbot Example

I recently developed a browser-based 聊天机器人. Synchronous behavior would have been undesirable as it would cause the conversation to appear disjointed and sluggish. My solution achieves well-paced conversation by asynchronously communicating with the ChatGPT external API to both send and receive messages.

To facilitate communication with the ChatGPT API,我创建了一个简单的Node.Js服务器使用 OpenAI. 然后我利用 异步JavaScript 获取 API that uses programmatic promises to provide a way to access and process responses:

  获取 (http://localhost: 5000 /, {
    方法:“文章”,
    标题:{
      “内容类型”:“application / json”
    },
    身体:JSON.stringify ({
      query: 'What is the weather like in Seattle?'
    })
  })
  .then(response => response.json ())
  .then(data => {
    控制台.日志(数据);
  });

Our simple server asynchronously calls the ChatGPT service 而 providing bidirectional message transmission.

另一个异步方法I 常用的是 setInterval (). This function provides a built-in timer that subsequently calls a function repeatedly at any specified interval. 使用 setInterval, I added a typing effect to the user interface, letting the user know that the other party (the 聊天机器人) is creating a response:

// Creating loader function for bot
函数加载器(元素){
    元素.textContent = ";

    // 300 ms allows for real-time responsiveness indicating other-party typing
    loadInterval = setInterval(() => {
        元素.textContent += '.';

        如果(元素.textContent === '....') {
            元素.textContent = ";
        }
    }, 300);
}

//创建输入功能
function typeText(元素, text) {
    设index = 0;
    // 20 ms allows for real-time responsiveness to mimic chat typing
    let interval = setInterval(() => {
        if (index < text.长度){
            元素.innerHTML += text.charAt(指数);
            指数+ +;
        } else {
            clearInterval(间隔);
        }
    }, 20);
}

These two asynchronous blocks turn an otherwise disjointed conversation into one in which participants feel engaged. But the responsiveness 异步JavaScript allows may be a less obvious key ingredient in other contexts.

More 异步 JavaScript Examples

Once I was tasked with creating a custom WordPress plugin that allowed users to upload large files asynchronously. 我用了 AJAX库 to allow the user to upload their files in the background without having to wait for the page to reload. This allowed for a much smoother user experience and the application was a huge success.

在另一个用例中 电子商务网站 was having trouble with slow loading times due to the large number of images it had to load. To speed up the process, I implemented an async JavaScript function (LazyLoading) to load each image asynchronously. This allowed the website to load faster, as the images weren’t all loaded at the same time.

I also worked on a project involving a money transfer application integrating various crypto and payment APIs. I needed to pull data from an external API, but the API took some time to respond. To ensure that the application didn’t grind to a halt 而 waiting for the API, I implemented an async function that was able to keep the application running 而 it waited for the API response, resulting in an enhanced user experience.

异步 methods in a JavaScript implementation allow for powerful functionality in the service of end users, 减少UI减速或冻结. That’s why 异步JavaScript is crucial to user retention in apps like Uber (running its booking and 付款流程 在后台), Twitter (loading the latest tweets in real time), and Dropbox (keeping users’ files synced and up to date across devices).

作为开发者, you may worry that 异步JavaScript methods won’t appear on the call stack as expected—but rest assured, 他们所做的. You may confidently include 异步功能 among your options in delivering superior user experiences.

The Toptal 工程 博客 extends its gratitude to 穆罕默德·阿西姆·比拉尔 for reviewing the technical content and code samples presented in this article.

了解基本知识

  • 什么是异步JavaScript?

    异步 programming allows code statements to execute without blocking subsequent processing. JavaScript runtimes simulate 异步功能 而 using a synchronous set of queues behind the scenes.

  • Is JavaScript asynchronous by default?

    No. 默认情况下, JavaScript是同步的, single-threaded programming language in which instructions run one after the other—not in parallel. 异步 techniques don’t change this fundamental limitation, but 他们所做的 help reduce programmatic blocking.

  • What are the benefits of asynchronous programming?

    异步 programming allows an application to stay responsive by avoiding slowdowns or front-end freezes.

聘请Toptal这方面的专家.
现在雇佣
穆罕默德·阿马尔·伊利亚斯

穆罕默德·阿马尔·伊利亚斯

验证专家 在工程
11 的经验

拉合尔,旁遮普,巴基斯坦

自2021年7月14日起成为会员

作者简介

Muhammad is a full-stack developer with more than a decade of experience delivering web and mobile applications for various companies, 包括观测仪的, Microblink, 和Resulta. He has JavaScript expertise ranging across Node.js,下一个.js, 反应, 反应 Native, and headless WordPress solutions.

authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.

以前的角色

高级WordPress开发人员

以前在

观测仪的

World-class articles, delivered weekly.

By entering your email, you are agreeing to our 隐私政策.

World-class articles, delivered weekly.

By entering your email, you are agreeing to our 隐私政策.

Toptal开发者

加入总冠军® 社区.