Преобразование методов nested .map с помощью модели async / await

#javascript #node.js #async-await

#javascript #node.js #async-await

Вопрос:

Я управляю файлом JSON, подобным этому примеру:

 [
    {
        "Item": "Item1",
        "ItemChild": [
            {
                "Category": "Category1",
                "Inputs": [
                    {
                        "InputName": "1",
                        "InputTitle": "Title1",
                    },
                ]
            },
            {
                "Category": "Category2",
                "Inputs": [
                    {
                        "InputName": "2",
                        "InputTitle": "Title2",
                    },
                ]
            }
        ]
    }
]
  

Я анализирую этот файл, получаю все Category InputName InputTitle значения ключей и и добавляю их в файл, используя эту логику:

 myParsedJSON.map(({ ItemChild }) => {
    ItemChild.map(({ Category, Inputs }) => {
         fs.appendFileSync(myfile, Category);
         Inputs.map(({ InputName, InputTitle }) => {
             fs.appendFileSync(myfile, InputName   ' - '   InputTitle);
         });
     });
});
  

Я хочу использовать асинхронную версию этой логики с моделью async / await и асинхронными операциями.
Каков наилучший способ сделать это?
Спасибо

Ответ №1:

Функции массива плохо работают async , поэтому преобразуйте их в for of циклы

 const fsp = require('fs').promises

for (const { ItemChild } of myParsedJSON) {
    for (const { Category, Inputs } of ItemChild) {
        await fsp.appendFile(myfile, Category);
        for (const { InputName, InputTitle } of Inputs) {
            await fsp.appendFile(myfile, `${InputName} - ${InputTitle}`);
        }
    }
}
  

Комментарии:

1. Спасибо!! @Matt, это решение очень простое и подходит для моего случая

Ответ №2:

Вам пришлось бы действительно исказить это, чтобы использовать async / await, хотя вы могли бы легко преобразовать его во что-то, что вы могли бы await где-то еще:

 const text = myParsedJSON.map(({ ItemChild }) => {
    return ItemChild
        .map(({ Category, Inputs }) => {
            return Category   'n'   Inputs
                .map(({ InputName, InputTitle }) => {
                    return InputName   ' - '   InputTitle;
                })
                .join('n');
        })
        .join('n');
});

const awaitableResult = new Promise((resolve, reject) => {
    fs.appendFile(myFile, text, (err) => {
        if (err) reject(err);
        resolve(true);
    });
});
  

Теперь вы можете await awaitableResult в любой async функции:

 async someFunction() {
    await awaitableResu< // file IO done.
    // do whatever needs to happen next.
}
  

Обратите внимание, что мы выполняем всю обработку данных перед началом записи в файл: запись на диск — это s-l-o-w, вы хотите делать это как можно реже. Если вы действительно хотите придерживаться поэтапного подхода, используйте fs.writeStream .

Комментарии:

1. Спасибо @Jared Smith, ваш ответ очень понятен и полезен для меня.