reduce
对数组中的每个元素执行异步归约操作,累积结果。
基础用法
typescript
import { reduce } from 'radash'
const numbers = [1, 2, 3, 4, 5]
const sum = await reduce(numbers, async (acc, num) => {
await new Promise(resolve => setTimeout(resolve, 100))
return acc + num
}, 0)
console.log(sum) // 15
语法
typescript
function reduce<T, U>(
array: readonly T[],
fn: (acc: U, item: T, index: number, array: readonly T[]) => Promise<U>,
initial: U
): Promise<U>
参数
array
(readonly T[]): 要处理的数组fn
(function): 异步归约函数acc
(U): 累积值item
(T): 当前元素index
(number): 当前元素的索引array
(readonly T[]): 原数组
initial
(U): 初始值
返回值
返回一个Promise,解析为最终的累积结果。
示例
基本异步归约
typescript
import { reduce } from 'radash'
const numbers = [1, 2, 3, 4, 5]
const sum = await reduce(numbers, async (acc, num) => {
await new Promise(resolve => setTimeout(resolve, 100))
return acc + num
}, 0)
console.log(sum) // 15
处理对象数组
typescript
import { reduce } from 'radash'
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
]
const userStats = await reduce(users, async (acc, user) => {
// 模拟异步操作
await new Promise(resolve => setTimeout(resolve, 50))
return {
totalAge: acc.totalAge + user.age,
names: [...acc.names, user.name],
count: acc.count + 1
}
}, { totalAge: 0, names: [], count: 0 })
console.log(userStats)
// { totalAge: 90, names: ['Alice', 'Bob', 'Charlie'], count: 3 }
处理API调用累积
typescript
import { reduce } from 'radash'
const userIds = [1, 2, 3, 4, 5]
const userData = await reduce(userIds, async (acc, userId) => {
const response = await fetch(`/api/users/${userId}`)
const user = await response.json()
return {
...acc,
[userId]: user,
totalUsers: acc.totalUsers + 1
}
}, { totalUsers: 0 })
console.log(userData)
处理文件内容累积
typescript
import { reduce } from 'radash'
async function processFiles(filePaths: string[]) {
return reduce(filePaths, async (acc, filePath) => {
const fs = await import('fs/promises')
const content = await fs.readFile(filePath, 'utf-8')
return {
...acc,
[filePath]: content.length,
totalSize: acc.totalSize + content.length
}
}, { totalSize: 0 })
}
const files = ['./file1.txt', './file2.txt', './file3.txt']
const fileStats = await processFiles(files)
console.log(fileStats)
处理数据库查询累积
typescript
import { reduce } from 'radash'
async function aggregateUserData(userIds: number[]) {
return reduce(userIds, async (acc, userId) => {
// 模拟数据库查询
const userResponse = await fetch(`/api/users/${userId}`)
const user = await userResponse.json()
const postsResponse = await fetch(`/api/users/${userId}/posts`)
const posts = await postsResponse.json()
return {
...acc,
users: [...acc.users, user],
totalPosts: acc.totalPosts + posts.length,
averageAge: (acc.averageAge * acc.users.length + user.age) / (acc.users.length + 1)
}
}, { users: [], totalPosts: 0, averageAge: 0 })
}
const userIds = [1, 2, 3]
const aggregated = await aggregateUserData(userIds)
console.log(aggregated)
处理条件累积
typescript
import { reduce } from 'radash'
const transactions = [
{ id: 1, amount: 100, type: 'income' },
{ id: 2, amount: 50, type: 'expense' },
{ id: 3, amount: 200, type: 'income' },
{ id: 4, amount: 75, type: 'expense' }
]
const balance = await reduce(transactions, async (acc, transaction) => {
await new Promise(resolve => setTimeout(resolve, 10))
if (transaction.type === 'income') {
return acc + transaction.amount
} else {
return acc - transaction.amount
}
}, 0)
console.log('Final balance:', balance) // 175
处理复杂对象累积
typescript
import { reduce } from 'radash'
interface Product {
id: number
name: string
price: number
category: string
}
const products: Product[] = [
{ id: 1, name: 'Laptop', price: 999, category: 'electronics' },
{ id: 2, name: 'Phone', price: 599, category: 'electronics' },
{ id: 3, name: 'Book', price: 19, category: 'books' },
{ id: 4, name: 'Tablet', price: 399, category: 'electronics' }
]
const productAnalysis = await reduce(products, async (acc, product) => {
// 模拟异步分析
await new Promise(resolve => setTimeout(resolve, 50))
return {
...acc,
totalValue: acc.totalValue + product.price,
categories: {
...acc.categories,
[product.category]: (acc.categories[product.category] || 0) + 1
},
averagePrice: (acc.averagePrice * acc.count + product.price) / (acc.count + 1),
count: acc.count + 1
}
}, { totalValue: 0, categories: {}, averagePrice: 0, count: 0 })
console.log(productAnalysis)
处理错误累积
typescript
import { reduce } from 'radash'
const operations = [
{ id: 1, shouldFail: false },
{ id: 2, shouldFail: true },
{ id: 3, shouldFail: false }
]
const results = await reduce(operations, async (acc, operation) => {
try {
if (operation.shouldFail) {
throw new Error(`Operation ${operation.id} failed`)
}
await new Promise(resolve => setTimeout(resolve, 100))
return {
...acc,
successful: [...acc.successful, operation.id],
totalProcessed: acc.totalProcessed + 1
}
} catch (error) {
return {
...acc,
failed: [...acc.failed, { id: operation.id, error: error.message }],
totalProcessed: acc.totalProcessed + 1
}
}
}, { successful: [], failed: [], totalProcessed: 0 })
console.log(results)
处理进度跟踪
typescript
import { reduce } from 'radash'
async function processWithProgress<T, U>(
items: T[],
fn: (acc: U, item: T, index: number) => Promise<U>,
initial: U,
onProgress?: (completed: number, total: number) => void
): Promise<U> {
let result = initial
for (let i = 0; i < items.length; i++) {
result = await fn(result, items[i], i)
if (onProgress) {
onProgress(i + 1, items.length)
}
}
return result
}
const tasks = ['task1', 'task2', 'task3', 'task4', 'task5']
const result = await processWithProgress(
tasks,
async (acc, task, index) => {
await new Promise(resolve => setTimeout(resolve, 1000))
return [...acc, `Completed ${task}`]
},
[],
(completed, total) => {
console.log(`Progress: ${completed}/${total} (${Math.round(completed/total*100)}%)`)
}
)
console.log(result)
处理嵌套数据累积
typescript
import { reduce } from 'radash'
interface Post {
id: number
title: string
authorId: number
tags: string[]
}
const posts: Post[] = [
{ id: 1, title: 'First Post', authorId: 1, tags: ['javascript', 'react'] },
{ id: 2, title: 'Second Post', authorId: 2, tags: ['typescript', 'vue'] },
{ id: 3, title: 'Third Post', authorId: 1, tags: ['javascript', 'node'] }
]
const postAnalysis = await reduce(posts, async (acc, post) => {
// 模拟获取作者信息
const authorResponse = await fetch(`/api/authors/${post.authorId}`)
const author = await authorResponse.json()
return {
...acc,
authors: {
...acc.authors,
[author.id]: {
...author,
postCount: (acc.authors[author.id]?.postCount || 0) + 1
}
},
tags: {
...acc.tags,
...post.tags.reduce((tagAcc, tag) => ({
...tagAcc,
[tag]: (acc.tags[tag] || 0) + 1
}), {})
},
totalPosts: acc.totalPosts + 1
}
}, { authors: {}, tags: {}, totalPosts: 0 })
console.log(postAnalysis)
处理批量操作累积
typescript
import { reduce } from 'radash'
async function processBatchWithAccumulation<T, U>(
items: T[],
batchSize: number,
fn: (acc: U, batch: T[]) => Promise<U>,
initial: U
): Promise<U> {
const batches: T[][] = []
for (let i = 0; i < items.length; i += batchSize) {
batches.push(items.slice(i, i + batchSize))
}
return reduce(batches, fn, initial)
}
const userIds = Array.from({ length: 100 }, (_, i) => i + 1)
const userStats = await processBatchWithAccumulation(
userIds,
10,
async (acc, batch) => {
const response = await fetch('/api/users/batch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: batch })
})
const users = await response.json()
return {
...acc,
totalUsers: acc.totalUsers + users.length,
averageAge: (acc.averageAge * acc.batchCount + users.reduce((sum, u) => sum + u.age, 0)) / (acc.batchCount + 1),
batchCount: acc.batchCount + 1
}
},
{ totalUsers: 0, averageAge: 0, batchCount: 0 }
)
console.log(userStats)
注意事项
- 顺序执行: 异步操作按顺序执行,不是并发的
- 错误处理: 如果任何操作失败,整个reduce操作会失败
- 性能: 适合需要累积结果的场景,不适合独立操作
- 内存: 累积值会持续增长,注意内存使用
- 初始值: 必须提供初始值
与其他方法的区别
Array.prototype.reduce()
: 同步操作,不支持异步reduce()
: radash提供的异步归约方法map()
: 处理独立操作,reduce()
处理累积操作
实际应用场景
- 数据聚合: 累积统计数据
- 文件处理: 累积文件内容或统计信息
- 数据库操作: 累积查询结果
- API调用: 累积多个API的响应数据
- 业务逻辑: 累积复杂的业务计算结果