1、Promises
Promises 提供了一种干净的方式来处理异步操作及其结果。以下是 Promise 的详细方法及更多示例:
Promise.resolve()
Promise.resolve()
方法返回一个以给定值解析的 Promise。
const resolvedPromise = Promise.resolve(42);
resolvedPromise.then(value => console.log(value)); // 42
Promise.reject()
Promise.reject()
方法返回一个带有给定原因的被拒绝的 Promise。
const rejectedPromise = Promise.reject("Error occurred");
rejectedPromise.catch(reason => console.error(reason)); // Error occurred
Promise.allSettled()
Promise.allSettled()
方法返回一个 Promise,当所有给定的 Promise 都已敲定(resolved 或 rejected)后,它会异步地解析这个 Promise,结果是一个对象数组。
const p1 = Promise.resolve(1);
const p2 = Promise.reject("Failed");
const p3 = Promise.resolve(3);
Promise.allSettled([p1, p2, p3]).then(results => {
results.forEach(result => console.log(result.status, result.value));
// fulfilled 1
// rejected Failed
// fulfilled 3
});
Promise.any()
Promise.any()
方法返回第一个成功决议的 Promise,如果全是被拒绝的 Promises,则返回一个 AggregateError。
const p1 = Promise.reject("Failed");
const p2 = Promise.resolve(2);
Promise.any([p1, p2]).then(value => {
console.log(value); // 2
}).catch(error => {
console.error(error);
});
2、Async/Await
async/await
是基于 Promises 构建的,用于简化异步代码的语法,并使其更加可读。
使用多个 await
你可以连续使用多个 await
来处理依次的异步操作。
async function asyncFunction() {
try {
const result1 = await asyncOperation1();
console.log(result1);
const result2 = await asyncOperation2();
console.log(result2);
} catch (error) {
console.error(error);
}
}
asyncFunction();
3、Generators
Generators 允许函数执行中途退出并在稍后恢复,保存其上下文(变量绑定)。
使用 Generators 和 Promises
将 Generators 和 Promises 结合使用来处理异步代码。
function asyncOperation() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Operation done");
}, 2000);
});
}
function* generatorFunction() {
const result = yield asyncOperation();
console.log(result);
}
const iterator = generatorFunction();
iterator.next().value.then(result => iterator.next(result));
4、使用 co
库
co
库可以帮助我们将 Generator 用于异步编程,非常类似于 async/await
。
const co = require('co');
function asyncOperation() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Operation done");
}, 2000);
});
}
co(function* () {
const result = yield asyncOperation();
console.log(result); // Operation done
}).catch(error => {
console.error(error);
});
5、Observables
Observables 是一种比 Promise 更强大的异步机制,主要通过 ReactiveX 库(如 RxJS)实现。
创建和订阅 Observable
以下是如何使用 RxJS 创建和订阅一个 Observable:
const { Observable } = require('rxjs');
// 创建一个 Observable
const observable = new Observable(subscriber => {
subscriber.next('Hello');
setTimeout(() => {
subscriber.next('World');
subscriber.complete();
}, 1000);
});
// 订阅一个 Observable
observable.subscribe({
next(x) { console.log(x); },
error(err) { console.error('Error: ' + err); },
complete() { console.log('Done'); }
});
RxJS 操作符
RxJS 提供了丰富的操作符来处理数据流(如映射、过滤、合并等)。
const { of } = require('rxjs');
const { map, filter } = require('rxjs/operators');
// 创建一个 Observable,并使用操作符处理数据流
const observable = of(1, 2, 3, 4, 5).pipe(
filter(x => x % 2 === 0),
map(x => x * 10)
);
observable.subscribe({
next(x) { console.log(x); }, // 20, 40
complete() { console.log('Done'); }
});
7、Async Iterators
Async Iterators 允许你定义一个可以暂停和恢复的函数,用于处理异步数据流。
创建一个 Async Iterator 并使用 for-await-of
循环
async function* asyncGenerator() {
const data = ['Hello', 'World', 'Async', 'Iteration'];
for (let item of data) {
await new Promise(resolve => setTimeout(resolve, 1000));
yield item;
}
}
// 使用 for-await-of 循环遍历 AsyncIterator
async function processAsyncIterable() {
for await (let value of asyncGenerator()) {
console.log(value);
}
}
processAsyncIterable();
8、Web Workers
Web Workers 允许你在一个后台线程运行 JavaScript,避免阻塞主线程的执行。
创建和使用 Web Worker
main.js
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
console.log('Received from worker:', event.data);
};
worker.postMessage('Hello from main thread');
worker.js
onmessage = function(event) {
console.log('Received from main thread:', event.data);
postMessage('Hello from worker thread');
};
复杂计算任务示例
main.js
const worker = new Worker('prime-worker.js');
worker.onmessage = function(event) {
console.log('Prime numbers:', event.data);
};
worker.postMessage(100000); // Find prime numbers up to 100000
prime-worker.js
function findPrimes(limit) {
const primes = [];
for (let i = 2; i <= limit; i++) {
let isPrime = true;
for (let j = 2; j <= Math.sqrt(i); j++) {
if (i % j === 0) {
isPrime = false;
break;
}
}
if (isPrime) primes.push(i);
}
return primes;
}
onmessage = function(event) {
const limit = event.data;
const primes = findPrimes(limit);
postMessage(primes);
};
9、Service Workers
Service Workers 是运行在浏览器后台的独立脚本,适用于实现离线缓存、推送通知、后台数据同步等功能。
注册和使用 Service Worker
index.html
<!DOCTYPE html>
<html>
<head>
<title>Service Worker Example</title>
</head>
<body>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(registration => {
console.log('Service Worker registered:', registration);
}).catch(error => {
console.error('Service Worker registration failed:', error);
});
}
</script>
</body>
</html>
service-worker.js
self.addEventListener('install', event => {
console.log('Service Worker installing.');
});
self.addEventListener('activate', event => {
console.log('Service Worker activating.');
});
self.addEventListener('fetch', event => {
console.log('Fetching:', event.request.url);
event.respondWith(fetch(event.request)); // 可在此处实现离线缓存逻辑
});
10、setTimeout 和 setInterval
setTimeout
setTimeout
用于在指定的时间间隔后执行一段代码。
setTimeout(() => {
console.log('Executed after 2 seconds');
}, 2000);
setInterval
setInterval
用于每隔指定的时间间隔执行一段代码。
const intervalId = setInterval(() => {
console.log('Executed every 1 second');
}, 1000);
// 停止执行
setTimeout(() => {
clearInterval(intervalId);
console.log('Interval cleared');
}, 5000);
11、Event Loop 和 Microtasks/Macrotasks
了解 JavaScript 的 Event Loop 机制对于理解异步编程非常重要。
事件循环示例
console.log('Script start');
setTimeout(() => {
console.log('setTimeout'); // Macrotask
}, 0);
new Promise((resolve) => {
console.log('Promise start');
resolve();
}).then(() => {
console.log('Promise then'); // Microtask
});
console.log('Script end');
输出顺序:
Script start
Promise start
Script end
Promise then
setTimeout
Microtasks (e.g., Promises)
Microtasks 在每一个循环迭代结束后执行,优先级高于 Macrotasks。
Promise.resolve().then(() => {
console.log('Microtask 1');
}).then(() => {
console.log('Microtask 2');
});
Macrotasks (e.g., setTimeout, setInterval)
Macrotasks 在每一个 Event Loop 周期结束时执行,优先级低于 Microtasks。
setTimeout(() => {
console.log('Macrotask 1');
}, 0);
setTimeout(() => {
console.log('Macrotask 2');
}, 0);
这些是 JavaScript 处理异步编程的其他一些方案,每种方法都有各自的适用场景和优缺点。通过适当地选择工具和方法,你可以更高效地处理异步任务,使代码更加简洁、可维护和高效。