【问题标题】:lodash mapValues asynclodash mapValues 异步
【发布时间】:2016-06-30 13:59:42
【问题描述】:

在 _.mapValues 内部,我想获得一些具有一定延迟的修改值(例如来自 DB),但我遇到了问题:当我在同步模式下修改值时,一切都很好,当我尝试使用 Promise 或回调它的工作时不正确(在第一种情况下,我得到 Promise 对象,在第二种情况下:未定义的值)。 这里有一些简化的例子,我如何在 mapValues 中重写代码来解决这个问题?

'use strict';
const _ = require('lodash');
const Promise = require('bluebird');

let obj = {
  one: 1,
  two: 2,
};

let increment = (value) => {
  return value + 1;
};

let incrementProm = (value) => {
  return Promise.resolve(value + 1);
};

let incrementCb = (value, cb) => {
  let res = value + 1;
  let err = null;
  setTimeout(cb.bind(undefined, err, res), 100);
};

let t1 = _.mapValues(obj, (value) => {
  return increment(value);
});

let t2 = _.mapValues(obj, (value) => {
  return incrementProm(value);
});

let t3 = _.mapValues(obj, (value) => {
  let temp;
  incrementCb(value, (err, res) => {
    temp = res;
  });
  return temp;
});

console.log('Sync res:');
console.log(t1);
console.log('Promise res:');
console.log(t2);
console.log('Callback res:');
console.log(t3);

【问题讨论】:

    标签: javascript node.js lodash


    【解决方案1】:

    您可以使用 bluebird 的 props() 函数来解析所有带有 Promise 的属性。

    Promise.props(_.mapValues(obj, incrementProm))
    .then(result => console.log(result));
    

    var obj = {
      one: 1,
      two: 2
    };
    
    var incrementProm = value => Promise.resolve(value + 1);
    
    Promise.props(_.mapValues(obj, incrementProm))
    .then(result => console.log(result));
    <script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.4.1/bluebird.js"></script>

    【讨论】:

    • 请注意 Promise.props() 是特定于 Bluebird 承诺的。如果您使用的是本机(或任何其他实现),您将不得不找到另一种方式
    【解决方案2】:

    你正在映射到 Promise,所以我做的事情可能是:

    var _ = require('lodash');
    let incrementProm = (value) => {
      return Promise.resolve(value + 1);
    };
    
    let obj = {
        foo: 1,
        bar: 2
    }
    
    let keys = _.keys(obj);
    let promises = _.map(keys, k => {
        return incrementProm(obj[k])
        .then(newValue => { return { key: k, value: newValue } });
    })
    Promise.all(promises).then(values => {
        values.forEach(v => obj[v.key] = v.value)
    })
    .then(() => {
        // now your object is updated: foo = 2 and bar = 3
        console.log(obj);
    });
    

    【讨论】:

      【解决方案3】:

      您可以实现 mapValues 的异步版本。比如……

      async function mapValuesAsync(object, asyncFn) {
        return Object.fromEntries(
          await Promise.all(
            Object.entries(object).map(async ([key, value]) => [
              key,
              await asyncFn(value, key, object)
            ])
          )
        );
      }
      

      然后像调用 _.mapValues 一样调用它:

      let t2 = await mapValuesAsync(obj, (value) => {
          return incrementProm(value);
      });
      

      或者,简单地说

      let t2 = await mapValuesAsync(obj, incrementProm);
      

      【讨论】:

        猜你喜欢
        • 2018-12-25
        • 1970-01-01
        • 2020-01-23
        • 1970-01-01
        • 1970-01-01
        • 2018-10-29
        • 2019-10-26
        • 1970-01-01
        • 2018-04-14
        相关资源
        最近更新 更多