【问题标题】:Array.Prototype ForEach Wait For Callback Function To Return In Recursive FunctionArray.Prototype ForEach 等待回调函数在递归函数中返回
【发布时间】:2019-08-23 15:39:04
【问题描述】:

我有一个循环遍历 javascript 对象的键的递归函数。这用于查找名称为“文件名”的所有键。当条件匹配时,我需要调用一个回调函数 base64,它将图像转换为 base64。我的问题是这个任务需要很长时间,并且由于它的异步性,循环甚至在它转换第一张图像之前就完成了。我试过使用异步库,但没有用,我很确定这是由于函数的递归性质。如何在回调返回结果之前暂停 foreach 循环的执行。

功能是

const iterate = (obj) =>
{
    Object.keys(obj).forEach((key) =>
    {
        if(key === 'filename')
        {
            base64.encode(`https://example.com/${obj[key]}`, { string: true }, (errr, encr) =>
            {
                obj[key] = encr;
            });
        }
        if(typeof obj[key] === 'object' && obj[key] !== null)
        {
            iterate(obj[key]);
        }
    });
};

【问题讨论】:

  • 你为什么要找到钥匙?你可以检查是否有一个密钥filename
  • 你为什么要这样做?
  • 嗯,我想检查是否有名为文件名的键,然后在找到它时对该键进行一些操作。该对象包含许多嵌套结构
  • 你仍然不需要在每个循环中等待异步代码完成,直到你不想在循环完成之前对异步代码的结果做任何事情,你不需要等待它。跨度>
  • 但是我在循环期间使用异步代码的结果来覆盖 obj[key] 的值。我注意到的行为是我能够在我的 console.logs 完成写入屏幕之前得到 express 的响应

标签: javascript node.js loops asynchronous


【解决方案1】:

你可以promisify你的方法然后等待。

 const Promise  = require('bluebird');
    let encode = Promise.promisify(base64.encode)

    const iterate = async (obj) =>
    {
        Object.keys(obj).forEach((key) =>
        {
            if(key === 'filename')
            {
                        obj[key] = await encode(`https://example.com/${obj[key]}`, { string: true });
            }
            if(typeof obj[key] === 'object' && obj[key] !== null)
            {
                iterate(obj[key]);
            }
        });
    };

【讨论】:

  • 有了这个我收到“语法错误:等待仅在异步函数中有效”的错误,它抱怨等待编码行
  • 你添加了 bluebird 和 promisify 吗?
  • 我做了 npm i bluebird promisify
  • 你需要做npm i bluebird然后在你的代码中添加这两行。
  • 是的,我已经安装了 bluebird 3.5.3 版
【解决方案2】:
//  SOLUTION 1
const async = require('async');

const iterator = (key, next) => {
  if(key === 'filename') {
      base64.encode(`https://example.com/${obj[key]}`, { string: true }, (errr, encr) => {
          obj[key] = encr;
          return next();
      });
  }
  return next();
};

async.each(Object.keys(obj), iterator, err => callback(err, obj));

您可以像这样使用async 库。 iterator 遍历键,如果键是file

//  SOLUTION 2
const getObj = (obj, callback) => {
    const { filename } = obj;
    if(!filename) return callback(null, obj);
    base64.encode(`https://example.com/${obj['filename']}`, { string: true }, (errr, encr) => {
      obj['filename'] = encr;
      return callback(errr, obj);
    });
};

getObj(obj, (err, newObj) => {
  // use any callback function that uses variable newObj
  // you can change obj by commenting out the line below
  // obj = newObj
}); 

或者由于obj是一个对象,你可以直接查找键并在运行回调的函数中使用它。

【讨论】:

  • 您的第一个解决方案给了我一个找不到迭代器的错误。您的第二个解决方案实际上并没有更改旧对象,回调返回的对象似乎根本没有更改数据。知道如何解决这个问题吗?
  • 嘿,解决了。解决方案 1 中的一些印刷错误和解决方案 2 中的返回值。请让我知道它是否有效
猜你喜欢
  • 2019-02-20
  • 2017-07-28
  • 1970-01-01
  • 2019-07-25
  • 2019-08-03
  • 2020-09-29
  • 1970-01-01
  • 2017-10-29
  • 2022-01-16
相关资源
最近更新 更多