Lodash链方法中的当前链

时间:2018-08-10 15:39:16

标签: javascript lodash lazy-evaluation

如果我有一个简单的lodash链来映射,然后过滤一个数组:

lodash.chain(myarray)
    .map(item=>{
        if (item === 'some-condition') return [item];
    })
    .filter(item=>!!item)
    .value();

显然,这是一个虚构的示例,但它与我一直以来所做的简单事情有关。基本上,数组映射不能返回某些映射,因此返回“ undefined”。然后,我过滤掉所有未定义的值。

由于它被大量使用,将它混入我的仪表板中是很有意义的。

所以:

const lodash = _.runInContext();

function mapFilter(ary, iterator) {
    return lodash.chain(ary)
        .map(iterator)
        .filter(item=>!!item)
        .value()
}

lodash.mixin(lodash, mapFilter, {chain:true});

很显然,我们可以做整件事而无需lodash,但通常,它可能是更大的链的一部分。从理论上讲,惰性评估可以使其更快。

我真正想要的是在我的混合方法中利用当前链(如果有)。否则,我将通过调用value()两次而失去惰性计算。

所以,如果我有更长的链条:

lodash.chain(myarray)
    .mapFilter( // do something) // my bespoke chainable method
    .map( // do something else )
    .sort()
    .value();

我想在我的定制方法中使用当前链(如果有)。像这样:

// This is made-up and does not work!
const lodash = _.runInContext();

function mapFilter(ary, iterator) {
    if (!!this.__currentChain) {
        return this.__currentChain.map(iterator).filter(item=>!!item);
    }
    return lodash.chain(ary)
        .map(iterator)
        .filter(item=>!!item)
        .value()
}

lodash.mixin(lodash, mapFilter, {chain:true});

显然,以上内容是虚构的,但希望它可以使我清楚地了解要实现的目标。我当然可以,只是没有我的功能,先做一个map()然后再做一个filter(),但是由于我做了很多,所以我希望减少打字。另外,示例可能更长,要做的更多,但仍想利用当前的链。

这可能吗?那是我的问题。显然,我可以想到一百万种替代解决方案,但我对此表示满意。只是想找一个时髦的专家说,“不可能” ,或者“是的,你这样做”。

2 个答案:

答案 0 :(得分:1)

我将其发布为评论,但是我觉得这是您想要的,既可以作为插入内容,也可以作为您需要检查其执行方式的源代码,然后编写自己的方法或从中获取内容的一部分您的mixin等。

lodash _.tap method的目的是tap into" a method chain sequence in order to modify intermediate results,因此您不必调用value等。您可以以此为起点。

希望这会有所帮助。

答案 1 :(得分:1)

检查函数是否在链中被调用的一种方法是检查this是否为LodashWrapper对象。然后,将第一个参数用作链中的迭代器。

const _ = require('lodash');

const lodash = _.runInContext();

function mapFilter(array, iterator) {
    if (this.constructor.name === 'LodashWrapper') {
        return this.map(array).filter(item => !!item);
    }
    else {
        return lodash.chain(array).map(iterator).filter(item => !!item).value();
    }
}

lodash.mixin({ mapFilter }, { chain: true });

const filter = x => x == 2 ? [x] : null;
console.log(lodash.mapFilter([1, 2, 3], filter));
console.log(lodash.chain([1, 2, 3]).mapFilter(filter).head().value());
console.log(lodash([1, 2, 3]).mapFilter(filter).head());

顺便说一句,当您使用显式_.chain时,lodash不会像您期望的那样应用快捷方式融合。因此,您可能需要使用隐式链接。有关详细信息,请参见Explicit chaining with lodash doesn't apply shortcut fusion