【问题标题】:Lodash: is it possible to use map with async functions?Lodash:可以将地图与异步功能一起使用吗?
【发布时间】:2018-04-14 09:29:32
【问题描述】:

考虑这段代码

const response  = await fetch('<my url>');
const responseJson = await response.json();
responseJson =  _.sortBy(responseJson, "number");

responseJson[0] = await addEnabledProperty(responseJson[0]);

addEnabledProperty 所做的是扩展对象,添加一个enabled 属性,但这并不重要。函数本身运行良好

async function addEnabledProperty (channel){

    const channelId = channel.id;
    const stored_status = await AsyncStorage.getItem(`ChannelIsEnabled:${channelId}`);
    let boolean_status = false;
    if (stored_status == null) {
        boolean_status = true;
    } else {
        boolean_status = (stored_status == 'true');
    }

    return _.extend({}, channel, { enabled: boolean_status });
}

有没有办法使用_.map(或其他系统)循环整个responseJson数组以对每个元素使用addEnabledProperty

我试过了:

responseJson = _.map(responseJson,  function(channel) {
            return addEnabledProperty(channell);
        });

但它没有使用异步,所以它冻结了应用程序。

我试过了:

responseJson = _.map(responseJson,  function(channel) {
            return await addEnabledProperty(chanell);
        });

但是我遇到了一个 js 错误(关于行 return await addEnabledProperty(chanell);

await 是保留字

然后尝试

responseJson = _.map(responseJson, async function(channel) {
            return await addEnabledProperty(channell);
        });

但是我得到了一系列 Promise...我不明白为什么...

还有什么!??

编辑:我了解您对我没有指定 addEnabledProperty() 返回 Promise 的抱怨,但是,真的,我不知道。事实上,我写了“我得到了一个 Promise 数组......我不明白为什么

【问题讨论】:

  • “但是我得到了一个 Promise 数组……我不明白为什么……” 因为 async 函数返回一个 Promise 并且 .map创建回调返回的值的数组。 Promise.all 是“解决”一系列承诺的方式。
  • 根据您的第三个示例,任何async 函数总是返回一个promise,这就是您获得它们数组的原因。但是,你可以试试:responseJson = await Promise.all(_.map(responseJson, function(channel) { return addEnabledProperty(channel) }))
  • await is a reserved word 你从哪里得到这个错误的?
  • addEnabledProperty 是否返回 Promise
  • @guest271314 我希望如此,因为 OP 在他的第一个 sn-p 中是 awaiting 它。编辑:我应该注意,等待非承诺仍然有效,所以也许它不是?。

标签: javascript async-await lodash


【解决方案1】:

要并行处理您的响应 json,您可以使用 Promise.all:

const responseJson = await response.json();
responseJson = _.sortBy(responseJson, "number");

let result = await Promise.all(_.map(responseJson, async (json) => 
  await addEnabledProperty(json))
);

由于addEnabledProperty 方法是异步的,以下也应该有效(根据@CRice):

let result = await Promise.all(_.map(responseJson, addEnabledProperty));

【讨论】:

  • 不需要async 匿名函数。 (json) =&gt; addEnabledProperty(json) 功能相同。另外,afaik,我们可以直接将该函数传递给地图,无需包装器:_.map(responseJson, addEnabledProperty)
  • @CRice "不需要异步匿名函数。" 如果 OP 期望返回 Promise 并使用 await,则 await 将如果async 不用于匿名箭头函数,则会导致错误
  • 这行得通,你让我明白了,使用await 使函数返回promise
  • @Crice 你能解释一下为什么在addEnabledProperty 上省略async await 时它仍然有效吗?
  • @Saitama 之所以有效,是因为您正在包装一个返回 Promise 的函数(我们知道,因为您需要使用 'await')与另一个仍然返回 Promise 的函数。而且由于匿名异步箭头的唯一参数被传递给“addEnabledProperty”,因此我们可以非常确定您不需要需要包装它。如果 'addEnabledProperty' 接受第二个(或第三个)参数,我们不想用从 _.map 传递的内容来污染,那将是必要的。
【解决方案2】:

您可以使用Promise.all() 运行数组中的所有承诺。

responseJson = await Promise.all(_.map(responseJson, (channel) => {
        return addEnabledProperty(channel);
    }));

【讨论】:

  • 无需声明此异步并等待addEnabledProperty。使用function(channel) { return addEnabledProperty(channel) } 将获得相同的结果。为了进一步简化:_.map(responseJson, addEnabledProperty) 避免不必要的包装函数。
  • @Crice 你能解释一下为什么不需要它吗?
  • 不需要,因为异步函数所做的只是返回一个承诺。你可以跳过它,直接返回 addEnabledProperty 承诺。
【解决方案3】:

我发现我不必将 async / await 放入 Promise.all 包装器中。

将这些知识与 lodash 链 (_.chain) 结合使用,可以得出以下简化版本的公认答案:

const responseJson = await Promise.all( _
                       .chain( response.json() )
                       .sortBy( 'number' )
                       .map( json => addEnabledProperty( json ) )
                       .value()
                     )

【讨论】:

    【解决方案4】:

    如何使用 partial.js(https://github.com/marpple/partial.js)

    它通过相​​同的代码涵盖了承诺和正常模式。

    _p.map([1, 2, 3], async (v) => await promiseFunction());
    

    【讨论】:

      猜你喜欢
      • 2021-08-23
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多