全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📝 1 篇文章 20 道配套习题

JS 异步进阶与并发控制

专题说明

本专题深入讲解JavaScript异步编程的进阶技术,涵盖异步迭代器、Generator函数与异步生成器、Web Workers多线程编程、Promise并发控制方法以及事件循环机制。适合已经掌握基础异步编程的开发者进阶学习。

学习目标

  1. 掌握异步迭代器的实现原理与 for await...of 语法
  2. 理解 Generator 函数的特性、yield 表达式及异步生成器的应用
  3. 学会使用 Web Workers 实现多线程并发计算
  4. 精通 Promise.all、Promise.race、Promise.allSettled 等并发控制方法
  5. 深入理解事件循环中微任务与宏任务的执行机制

学习内容

本专题涵盖以下核心知识点:

  • 异步迭代器与 for await...of:异步迭代器协议、手动实现异步迭代器、错误处理与提前终止
  • Generator函数与异步生成器:yield表达式传值、return/throw方法、yield*委托、async Generator
  • Web Workers与多线程:Worker线程池、数据传输机制、SharedArrayBuffer与Atomics原子操作
  • 并发控制:Promise.all/race/allSettled/any特性对比、并发限制实现、取消机制
  • 事件循环:微任务与宏任务执行顺序、Node.js与浏览器差异、queueMicrotask应用

学习建议

  1. 先理解基础Promise和async/await,再学习本专题内容
  2. 重点掌握异步迭代器和Generator的结合应用场景
  3. Web Workers部分需要实践操作,建议在浏览器环境中调试
  4. 事件循环机制建议画出执行流程图辅助理解
  5. 并发控制部分要理解各方法的适用场景和错误处理策略

📝 发现内容有误?点击此处直接编辑

📝 配套习题(20 题)

1
单选题

以下代码的输出结果是什么?

JavaScript
async function* asyncGenerator() {
    yield Promise.resolve(1);
    yield Promise.resolve(2);
    yield Promise.resolve(3);
}

(async () => {
    for await (const value of asyncGenerator()) {
        console.log(value);
    }
})();
A

1, 2, 3 依次输出

B

Promise {1}, Promise {2}, Promise {3} 依次输出

C

undefined 输出三次

D

报错:asyncGenerator 不是可迭代对象

2
多选题

关于异步迭代器和 for await...of,以下说法正确的有哪些?

A

异步迭代器必须实现 [Symbol.asyncIterator]() 方法

B

普通迭代器(实现 [Symbol.iterator]())也可以用于 for await...of

C

异步迭代器的 next() 方法必须返回 Promise<{value, done}>

D

for await...of 只能在 async 函数或模块顶层使用

E

Node.js 的可读流默认实现了异步迭代器接口

3
单选题

以下代码的输出结果是什么?

JavaScript
async function* asyncGen() {
    yield 1;
    throw new Error('generator error');
    yield 2;
}

(async () => {
    try {
        for await (const val of asyncGen()) {
            console.log(val);
            if (val === 1) break;
        }
    } catch (e) {
        console.log('caught:', e.message);
    }
})();
A

1, 然后 caught: generator error

B

1, 然后 caught: generator error, 再输出 2

C

只输出 1

D

报错,break 不能用于 for await...of

4
判断题

对象可以同时实现 [Symbol.iterator]()[Symbol.asyncIterator](),使其既支持 for...of 又支持 for await...of

A

B

5
填空题

请填写异步迭代器的完整实现:

JavaScript
const asyncRange = {
    from: 1,
    to: 5,

    [!!1!!]() {
        return {
            current: this.from,
            last: this.to,

            async !!2!!() {
                if (this.current <= this.last) {
                    await new Promise(resolve => setTimeout(resolve, 100));
                    return { !!3!!: this.current++, !!4!!: false };
                } else {
                    return { !!5!!: true };
                }
            }
        };
    }
};
6
单选题

以下代码的输出结果是什么?

JavaScript
function* generator() {
    const x = yield 1;
    const y = yield x + 2;
    return y + 3;
}

const gen = generator();
console.log(gen.next());
console.log(gen.next(10));
console.log(gen.next(20));
A

{value: 1, done: false}, {value: 12, done: false}, {value: 23, done: true}

B

{value: 1, done: false}, {value: 2, done: false}, {value: 3, done: true}

C

{value: undefined, done: false}, {value: 12, done: false}, {value: 23, done: true}

D

{value: 1, done: false}, {value: 10, done: false}, {value: 20, done: true}

7
单选题

以下代码的输出结果是什么?

JavaScript
function* gen() {
    try {
        yield 1;
        yield 2;
        yield 3;
    } finally {
        console.log('cleanup');
    }
}

const g = gen();
console.log(g.next());
console.log(g.return(100));
console.log(g.next());
A

{value:1,done:false}, {value:100,done:true}, cleanup输出, {value:undefined,done:true}

B

{value:1,done:false}, cleanup输出, {value:100,done:true}, {value:undefined,done:true}

C

{value:1,done:false}, {value:100,done:true}, {value:undefined,done:true}

D

{value:1,done:false}, cleanup输出, {value:100,done:true}, cleanup输出

8
单选题

以下代码的输出结果是什么?

JavaScript
async function* fetchPages(urls) {
    for (const url of urls) {
        const response = await fetch(url);
        const data = await response.json();
        yield data;
    }
}

const urls = ['url1', 'url2', 'url3'];
const gen = fetchPages(urls);

// 假设每个请求返回 { page: 1 }, { page: 2 }, { page: 3 }
(async () => {
    for await (const data of gen) {
        console.log(data.page);
    }
})();
A

1, 2, 3 依次输出

B

Promise 对象依次输出

C

undefined 输出三次

D

报错:async Generator 不能用于 for await...of

9
判断题

Generator 函数不能作为构造函数使用,不能通过 new 关键字调用。

A

B

10
单选题

以下关于 Web Worker 的说法,哪一项是错误的?

A

Web Worker 在独立的线程中运行,不阻塞主线程

B

Web Worker 不能直接访问 DOM 元素

C

Web Worker 可以通过 postMessage 与主线程通信

D

Web Worker 可以直接操作主线程的全局变量

E

Web Worker 可以使用 XMLHttpRequest 或 fetch 进行网络请求

11
多选题

关于 Web Worker 与主线程之间的数据传输,以下说法正确的有哪些?

A

postMessage 传输的数据会被结构化克隆,不是直接共享引用

B

使用 Transferable 对象传输时,原线程会失去对该对象的访问权

C

SharedArrayBuffer 可以实现主线程与 Worker 之间的零拷贝数据共享

D

ArrayBuffer、MessagePort、ImageBitmap 是可转移对象

E

Worker 可以通过 importScripts 加载外部脚本

12
单选题

以下代码实现了一个简单的 Worker 线程池,请问 Worker 完成任务后会发生什么?

JavaScript
class WorkerPool {
    constructor(numWorkers) {
        this.workers = [];
        this.taskQueue = [];
        this.activeTasks = new Map();

        for (let i = 0; i < numWorkers; i++) {
            const worker = new Worker('worker.js');
            worker.busy = false;
            this.workers.push(worker);
        }
    }

    runTask(data) {
        const availableWorker = this.workers.find(w => !w.busy);
        if (availableWorker) {
            return this.executeOn(availableWorker, data);
        } else {
            return new Promise(resolve => {
                this.taskQueue.push({ data, resolve });
            });
        }
    }

    executeOn(worker, data) {
        worker.busy = true;
        return new Promise(resolve => {
            const taskId = Date.now() + Math.random();
            this.activeTasks.set(taskId, resolve);
            worker.postMessage({ taskId, data });
        });
    }

    handleResult(worker, taskId, result) {
        const resolve = this.activeTasks.get(taskId);
        if (resolve) {
            resolve(result);
            this.activeTasks.delete(taskId);
        }
        worker.busy = false;
        if (this.taskQueue.length > 0) {
            const next = this.taskQueue.shift();
            this.executeOn(worker, next.data).then(next.resolve);
        }
    }
}
A

Worker 完成任务后被销毁,不再可用

B

Worker 完成任务后变为空闲状态,自动处理队列中的下一个任务

C

所有 Worker 必须等待队列清空才能继续处理

D

任务队列中的任务会被丢弃

13
判断题

调用 worker.terminate() 会立即终止 Worker 线程,Worker 内部无法阻止或感知这一终止操作。

A

B

14
单选题

以下代码的输出结果是什么?

JavaScript
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.reject('error');

Promise.all([p1, p2, p3])
    .then(results => console.log('success:', results))
    .catch(error => console.log('error:', error));

Promise.all([p1, p2])
    .then(results => console.log('success:', results));
A

error: error, success: [1, 2]

B

error: error, success: [1, 2, error]

C

success: [1, 2], error: error

D

error: error, 没有其他输出

15
单选题

以下代码的输出结果是什么?

JavaScript
const slow = new Promise(resolve => setTimeout(() => resolve('slow'), 500));
const fast = new Promise(resolve => setTimeout(() => resolve('fast'), 100));
const fail = new Promise((_, reject) => setTimeout(() => reject('fail'), 200));

Promise.race([slow, fast, fail])
    .then(result => console.log('then:', result))
    .catch(error => console.log('catch:', error));

Promise.race([slow, fail])
    .then(result => console.log('then2:', result))
    .catch(error => console.log('catch2:', error));
A

then: fast, catch2: fail

B

catch: fail, then2: slow

C

then: fast, then2: slow

D

catch: fail, catch2: fail

16
多选题

关于 Promise 的并发方法,以下说法正确的有哪些?

A

Promise.all 返回的结果数组顺序与 Promise 完成顺序一致

B

Promise.allSettled 返回的结果数组顺序与传入顺序一致

C

Promise.race 返回最先完成的 Promise 的结果

D

Promise.all 空数组会立即 resolve 为空数组

E

Promise.any 只要有一个 resolve 就 resolve,全部 reject 才 reject

17
单选题

以下代码实现了批量请求的并发限制,请问当 limit = 2 时,最多同时有多少个请求在执行?

JavaScript
async function requestWithLimit(urls, limit) {
    const results = [];
    const executing = new Set();

    for (const url of urls) {
        const promise = fetch(url).then(result => {
            executing.delete(promise);
            return result;
        });

        executing.add(promise);
        results.push(promise);

        if (executing.size >= limit) {
            await Promise.race(executing);
        }
    }

    return Promise.all(results);
}
A

最多 1 个

B

最多 2 个

C

最多 limit + 1 个

D

不确定,取决于请求完成速度

18
单选题

以下代码的输出顺序是什么?

JavaScript
console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve()
    .then(() => console.log('3'))
    .then(() => console.log('4'));

console.log('5');
A

1, 5, 3, 4, 2

B

1, 5, 2, 3, 4

C

1, 2, 3, 4, 5

D

1, 5, 3, 2, 4

19
单选题

以下代码的输出顺序是什么?

JavaScript
console.log('start');

setTimeout(() => {
    console.log('timeout');
    Promise.resolve().then(() => console.log('timeout promise'));
}, 0);

Promise.resolve()
    .then(() => {
        console.log('promise1');
        setTimeout(() => console.log('promise timeout'), 0);
    })
    .then(() => console.log('promise2'));

console.log('end');
A

start, end, promise1, promise2, timeout, timeout promise, promise timeout

B

start, end, promise1, timeout, promise2, timeout promise, promise timeout

C

start, end, promise1, promise2, timeout, promise timeout, timeout promise

D

start, end, timeout, promise1, promise2, timeout promise, promise timeout

20
填空题

请填写输出结果:

JavaScript
console.log('A');

queueMicrotask(() => console.log('!!1!!'));

Promise.resolve().then(() => console.log('!!2!!'));

setTimeout(() => console.log('!!3!!'), 0);

console.log('!!4!!');
← 上一个专题 JS 异步编程入门
下一个专题 → JS 运算符与流程控制

📝 发现内容有误?点击此处直接编辑

想查看更多习题和详细解析?
小程序提供完整的题库和详细解析

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库