关于js的map函数:
Array.map() 会一次性遍历数组的所有元素,并返回一个新的数组,其中每个元素是原数组元素经过提供的回调函数处理后的结果。map 方法会立即对整个数组进行操作并返回一个新数组,这个过程是同步的。
工作原理:
map() 会一次性遍历整个数组并返回新数组。它不会等到某个元素的处理完成才继续下一个元素,而是并行处理整个数组。注意: map() 不会改变原始数组,而是返回一个新的数组。
语法:
const newArray = array.map((element, index, array) => {
// 返回新元素
return newElement;
});
异步操作:
如果在 map() 的回调函数中执行异步操作(如 setTimeout 或 Promise),map() 会立即返回新数组,但异步操作会在未来的某个时刻完成,可能不会按预期顺序执行。若需要处理异步操作,可以结合 Promise.all 来确保异步操作完成后再处理结果。
示例:
const fetchData = async (id: number) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(`Data for ID: ${id}`);
}, 1000);
});
};
const main = async () => {
const ids = [1, 2, 3];
const results = await Promise.all(ids.map(async (id) => {
const data = await fetchData(id);
return data;
}));
console.log(results); // ["Data for ID: 1", "Data for ID: 2", "Data for ID: 3"]
};
main();
开始没有使用 main 包一下,结果报:
await is only valid in async functions and the top level bodies of modules
原因是await 只能在以下两种环境中使用:
1.异步函数 (async 函数) 内。
2.模块的顶层代码(type="module" 或 .mjs 文件)。
如下 .mjs 文件:
const fetchData = async (id) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(`Data for ID: ${id}`);
}, 1000);
});
};
const ids = [1, 2, 3];
const results = await Promise.all(ids.map(async (id) => {
const data = await fetchData(id);
return data;
}));
console.log(results); // ["Data for ID: 1", "Data for ID: 2", "Data for ID: 3"]
如下 html 中:
<script type="module">
const fetchData = async (id) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(`Data for ID: ${id}`);
}, 1000);
});
};
const ids = [1, 2, 3];
const results = await Promise.all(ids.map(async (id) => {
const data = await fetchData(id);
return data;
}));
console.log(results); // ["Data for ID: 1", "Data for ID: 2", "Data for ID: 3"]
</script>
使用 Promise.all 的好处
1.并行执行:
Promise.all 会并行执行所有异步任务,效率更高。
例如,上述代码中所有 fetchData 调用会在同一时间触发,而不是逐个等待。
2.统一处理结果:
如果需要一次性获得所有结果,可以直接使用 Promise.all,无需手动遍历。
3.简洁性:
代码更简单,逻辑更清晰。
相关使用场景:
1.并行获取多个数据:
例如从多个 API 请求数据时:
const urls = ['https://api.example.com/user', 'https://api.example.com/posts'];
const results = await Promise.all(urls.map(url => fetch(url).then(res => res.json())));
console.log(results); // [user data, posts data]
2.批量处理文件或任务: 当有一组任务需要并行执行时,Promise.all 是最佳选择:
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
const contents = await Promise.all(files.map(file => readFile(file, 'utf8')));
console.log(contents); // [content1, content2, content3]
当 任何一个 Promise 被拒绝(rejected),Promise.all 会立即抛出错误,并停止收集结果:
const promises = [
Promise.resolve('Task 1 success'),
Promise.reject('Task 2 failed'), // 会中断整个 Promise.all
Promise.resolve('Task 3 success')
];
try {
const results = await Promise.all(promises);
console.log(results); // 不会被执行
} catch (error) {
console.error('Error:', error); // 输出 "Error: Task 2 failed"
}
如果希望 Promise.all 在某些任务失败时依然返回其他任务的结果,可以使用 .catch 捕获错误:
const promises = [
Promise.resolve('Task 1 success'),
Promise.reject('Task 2 failed').catch(err => err), // 捕获错误,返回默认值
Promise.resolve('Task 3 success')
];
const results = await Promise.all(promises);
console.log(results); // ["Task 1 success", "Task 2 failed", "Task 3 success"]
总结:
async 函数返回一个 Promise:
即使返回的是普通值,也会被隐式包裹成 Promise。
示例:return 42 相当于 return Promise.resolve(42)。
await 暂停代码执行:
它会等待一个 Promise 被解决,并直接返回结果。
只能在 async 函数中使用,因为 async 提供了处理 Promise 的上下文。
优势:
简化异步代码逻辑,使其更接近同步代码风格。
提升可读性,避免 then 链式调用的复杂嵌套。
也就是说: 使用了 await,意味着它后面的表达式一定是一个 Promise 或者一个可以被隐式转换为 Promise 的值。await 的核心作用就是等待一个 Promise 的解决,并直接返回它的结果,这样可以让我们用一种更直观的方式来处理异步操作。
