Serial and parallel execution
ECMAScript 6 Serial Execution
ECMAScript 6 introduced several mechanisms to handle serial execution, the most important of which are Promises and async/await. Serial execution refers to tasks being executed one after another in sequence, where the next task starts only after the previous one has completed.
Promise Chaining
The then
method of Promises can be chained to achieve serial execution:
function task1() {
return new Promise(resolve => {
setTimeout(() => {
console.log('Task 1 completed');
resolve(1);
}, 1000);
});
}
function task2(value) {
return new Promise(resolve => {
setTimeout(() => {
console.log('Task 2 completed, received value:', value);
resolve(value + 1);
}, 500);
});
}
task1()
.then(task2)
.then(result => {
console.log('Final result:', result);
});
async/await Syntax
async/await makes serial code more intuitive:
async function serialExecution() {
const result1 = await task1();
const result2 = await task2(result1);
console.log('Final result:', result2);
}
serialExecution();
ECMAScript 6 Parallel Execution
Parallel execution refers to launching multiple tasks simultaneously without waiting for the previous task to complete. ECMAScript 6 provides several ways to achieve parallel execution.
Promise.all
Promise.all
can execute multiple Promises in parallel and return an array of results once all Promises are completed:
function fetchUser(id) {
return new Promise(resolve => {
setTimeout(() => resolve({ id, name: `User${id}` }), Math.random() * 1000);
});
}
Promise.all([fetchUser(1), fetchUser(2), fetchUser(3)])
.then(users => {
console.log('All user data:', users);
});
Promise.race
Promise.race
returns the result of the first completed Promise:
function timeout(ms) {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), ms);
});
}
Promise.race([fetchUser(1), timeout(500)])
.then(user => console.log('Fetched user:', user))
.catch(err => console.error('Error:', err.message));
Combining Serial and Parallel Execution
In real-world development, it's common to mix serial and parallel execution:
async function complexExecution() {
// Fetch basic information in parallel
const [user, posts] = await Promise.all([
fetchUser(1),
fetchPosts(1)
]);
// Process dependent data serially
const comments = await fetchComments(posts[0].id);
return { user, posts, comments };
}
complexExecution().then(data => console.log(data));
Error Handling Strategies
Different execution methods require different error handling approaches:
Serial Error Handling
async function serialWithErrorHandling() {
try {
const result1 = await mightFail();
const result2 = await anotherTask(result1);
return result2;
} catch (error) {
console.error('Execution failed:', error);
throw error; // Optionally rethrow or handle
}
}
Parallel Error Handling
Promise.all([
task1().catch(err => ({ error: err })),
task2().catch(err => ({ error: err }))
])
.then(results => {
const errors = results.filter(r => r.error);
if (errors.length) {
console.error('Some tasks failed:', errors);
}
return results;
});
Performance Considerations
Parallel execution can significantly improve performance, but the following should be noted:
- Browser parallel request limits (typically 6)
- Memory consumption
- CPU-intensive tasks may block the main thread
// Execute in parallel batches
async function batchParallel(tasks, batchSize = 5) {
const results = [];
for (let i = 0; i < tasks.length; i += batchSize) {
const batch = tasks.slice(i, i + batchSize);
const batchResults = await Promise.all(batch.map(task => task()));
results.push(...batchResults);
}
return results;
}
Advanced Patterns
Cancelable Promises
function cancellablePromise(promise) {
let cancel;
const wrappedPromise = new Promise((resolve, reject) => {
cancel = () => reject(new Error('Cancelled'));
promise.then(resolve, reject);
});
return { promise: wrappedPromise, cancel };
}
const { promise, cancel } = cancellablePromise(fetchUser(1));
setTimeout(cancel, 500); // Cancel after 500ms
Progress-aware Promises
function progressPromise(executor) {
const handlers = [];
const promise = new Promise((resolve, reject) => {
executor(
value => resolve(value),
reason => reject(reason),
progress => handlers.forEach(h => h(progress))
);
});
promise.onProgress = handler => {
handlers.push(handler);
return promise;
};
return promise;
}
const pp = progressPromise((resolve, reject, progress) => {
let p = 0;
const interval = setInterval(() => {
p += 10;
progress(p);
if (p >= 100) {
clearInterval(interval);
resolve('Completed');
}
}, 200);
});
pp.onProgress(p => console.log(`Progress: ${p}%`));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:错误处理模式
下一篇:async函数返回值