You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于JavaScript中Async与Promise的技术疑问

JavaScript Async 与 Promise 常见疑问解答

1. JavaScript是否只能通过XMLHttpRequest、DOM、setTimeout这类Web API/函数实现异步执行?

不是。JS的异步核心是事件循环,只要能把任务放到宏任务或微任务队列里,就能实现异步。除了你提到的Web API,还可以用:

  • Promise、async/await(本质是Promise的语法糖)
  • queueMicrotask() 直接创建微任务
  • Node.js环境下的fs.promises、child_process等内置异步API
    不需要局限于特定的几个Web API。

2. 我们能否自定义异步执行的函数?

当然可以,有两种常见方式:

  • 写一个返回Promise的函数,在内部控制异步逻辑
  • 用async关键字定义函数(这类函数默认返回Promise,配合await使用更简洁)

示例代码:

// 方式1:返回Promise
function delay(ms) {
  return new Promise(resolve => {
    setTimeout(() => resolve(`延迟${ms}ms完成`), ms);
  });
}

// 方式2:async函数
async function fetchData() {
  await delay(1000);
  return "模拟获取的数据";
}

3. 自定义的Promise函数是否会异步执行?

要看具体实现:

  • Promise构造函数的执行器函数(也就是你传入的(resolve, reject) => {})是同步执行的,创建Promise时就会立刻跑这部分代码
  • 但then()、catch()、finally()里的回调是异步微任务,会等同步代码执行完才运行

如果想让自定义函数的核心逻辑异步,得把耗时操作放到Web API(比如setTimeout)或queueMicrotask里,避免阻塞主线程。

4. 如下示例代码的输出顺序为HELLO、WORLD、FROM PROMISE,是否说明这段代码是异步执行的?

// Example, does the code run asynchronously? 
function showText() {
  return new Promise((resolve) => {
    resolve("FROM PROMISE");
  });
}

console.log("HELLO");
showText().then((res) => console.log(res));
console.log("WORLD");

// Output
// HELLO
// WORLD
// FROM PROMISE

是的,这段代码的异步特性体现在then()的回调上,执行流程是:

  1. 同步打印HELLO
  2. 调用showText(),执行器同步调用resolve,将Promise设为完成状态,同时把then()的回调加入微任务队列
  3. 同步打印WORLD
  4. 所有同步代码执行完毕,事件循环处理微任务队列,执行then()回调打印FROM PROMISE

正是因为then()回调是异步的,才会出现WORLD在FROM PROMISE之前输出的顺序。

5. 如下示例代码中,为何WORLD没有立即输出,而是和count函数的结果几乎同时出现?

function count() { // imagine this function is heavy and take a time to run it
  return new Promise((resolve, reject) => {
    let num = 0;
    for (let i = 1; i <= 10000000000; i++) {
      num += 1;
    }
    resolve(num);
  });
}

console.log("HELLO");
count().then((res) => console.log(res));
console.log("WORLD");

// Output
// HELLO
// WORLD
// 10000000000

核心原因是:count()里的超大for循环是同步执行的!

Promise的执行器函数会在创建Promise时立刻同步运行,这个循环耗时极长,直接阻塞了主线程。在循环结束前,后面的console.log("WORLD")根本没机会执行。完整流程是:

  1. 同步打印HELLO
  2. 调用count(),立刻执行执行器里的for循环,主线程被卡住
  3. 循环结束后,调用resolve(num),then()回调被加入微任务队列
  4. 主线程从count()返回,才执行console.log("WORLD")
  5. 同步代码执行完毕,处理微任务队列,打印10000000000

所以你看到WORLD和结果几乎同时出现,是因为WORLD必须等循环结束才能打印,而结果紧接着从微任务输出。如果想让count逻辑真正异步,得把循环放到Web API(比如setTimeout)或Worker线程里,避免阻塞主线程。


内容的提问来源于stack exchange,提问作者mrr dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:37:20