设为首页 加入收藏

TOP

Javascript中数组方法reduce的妙用之处(二)
2019-09-17 19:08:44 】 浏览:50
Tags:Javascript 方法 reduce 妙用
ding, maxReading}); // {minReading: 0.2, maxReading: 5.5}

这需要遍历我们的数组两次。但是,有时我们可能不想这样做。因为.reduce()让我们返回我们想要的任何类型,我们不必返回数字。我们可以将两个值编码到一个对象中。然后我们可以在每次迭代时进行两次计算,并且只遍历数组一次:

const readings = [0.3, 1.2, 3.4, 0.2, 3.2, 5.5, 0.4];
function minMaxReducer(acc, reading) {
    return {
        minReading: Math.min(acc.minReading, reading),
        maxReading: Math.max(acc.maxReading, reading),
    };
}
const initMinMax = {
    minReading: Number.MAX_VALUE,
    maxReading: Number.MIN_VALUE,
};
const minMax = readings.reduce(minMaxReducer, initMinMax);
console.log(minMax);
// {minReading: 0.2, maxReading: 5.5}

将映射和过滤合并为一个过程

还是先前那个用户列表,我们希望找到没有电子邮件地址的人的用户名,返回它们用户名用逗号拼接的字符串。一种方法是使用两个单独的操作:

  • 获取过滤无电子邮件后的条目
  • 获取用户名并拼接

将它们放在一起可能看起来像这样:

function notEmptyEmail(x) {
   return !!x.email
}

function notEmptyEmailUsername(a, b) {
    return a ? `${a},${b.username}` : b.username
}

const userWithEmail = userList.filter(notEmptyEmail);
const userWithEmailFormatStr = userWithEmail.reduce(notEmptyEmailUsername, '');

console.log(userWithEmailFormatStr);
// 'john,jerry'

现在,这段代码是完全可读的,对于小的样本数据不会有性能问题,但是如果我们有一个庞大的数组呢?如果我们修改我们的reducer回调,那么我们可以一次完成所有事情:

function notEmptyEmail(x) {
   return !!x.email
}

function notEmptyEmailUsername(usernameAcc, person){
    return (notEmptyEmail(person))
        ? (usernameAcc ? `${usernameAcc},${person.username}` : `${person.username}`) : usernameAcc;
}

const userWithEmailFormatStr = userList.reduce(notEmptyEmailUsername, '');

console.log(userWithEmailFormatStr);
// 'john,jerry'

在这个版本中,我们只遍历一次数组,一般建议使用filtermap的组合,除非发现性能问题,才推荐使用reduce去做优化。

按顺序运行异步函数

我们可以做的另一件事.reduce()是按顺序运行promises(而不是并行)。如果您对API请求有速率限制,或者您需要将每个prmise的结果传递到下一个promise,reduce可以帮助到你。

举一个例子,假设我们想要为userList数组中的每个人获取消息。

function fetchMessages(username) {
    return fetch(`https://example.com/api/messages/${username}`)
        .then(response => response.json());
}

function getUsername(person) {
    return person.username;
}

async function chainedFetchMessages(p, username) {
    // In this function, p is a promise. We wait for it to finish,
    // then run fetchMessages().
    const obj  = await p;
    const data = await fetchMessages(username);
    return { ...obj, [username]: data};
}

const msgObj = userList
    .map(getUsername)
    .reduce(chainedFetchMessages, Promise.resolve({}))
    .then(console.log);
// {glestrade: [ … ], mholmes: [ … ], iadler: [ … ]}

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

请注意,在此我们传递Promise作为初始值Promise.resolve(),我们的第一个API调用将立即运行。

下面是不使用async语法糖的版本

function fetchMessages(username) {
    return fetch(`https://example.com/api/messages/${username}`)
        .then(response => response.json());
}

function getUsername(person) {
    return person.username;
}

function chainedFetchMessages(p, username) {
    // In this function, p is a promise. We wait for it to finish,
    // then run fetchMessages().
    return p.then((obj)=>{
        return fetchMessages(username).then(data=>{
            return {
                ...obj,
                [username]: data
            }
        })
    })
}

const msgObj = peopleArr
    .map(getUsername)
    .reduce(chainedFetchMessages, Promise.resolve({}))
    .then(console.log);
// {glestrade: [ … ], mholmes: [ … ], iadler: [ … ]}

PS:更多前端资讯、技术干货,请关注公众号「前端新视界

前端新视界

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JavaScript(JS)的简单使用 下一篇自定义分页模板(银角大王版)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目