Проблема с использованием промисов
Всем здравствуйте.
Возникла проблема с работой цикла в функции, из-за асинхронного его выполнения. Изначально я его сделал на XMLHttpReuqest, где принудительно указывал запрет на асинхронность параметром false, но потребовалось переделать на fetch, и тут у меня возникли проблемы, как я понимаю мне надо все переделать на промисы .then, но что-то я не догоняю как правильно это сделать. Не пинайте сильно, это мой первый код не только на js, а в принципе. https://learn.javascript.ru/promise-basics <- данную статью читал, и не вкурил совсем. const express = require('express'); const fetch = require('node-fetch'); const app = express(); const port = 3000; const excel = require('exceljs'); const workbook = new excel.Workbook(); //Заносим в опцию токен для Синтека const options = { headers: { ZakupayToken: '***' } }; //Обновляем справочники let payers; let acceptor; fetch('https://***/api/v1/refbooks/offerPayers?', options) .then(response => response.json()) .then(data => payers = data.payers); fetch('https://***/api/v1/refbooks/offerAcceptors?', options) .then(response => response.json()) .then(data => acceptor = data.acceptors) .then(() => acceptor.splice(0,0,{ "firstName":"", "id":"", "lastName":"Любой" })); //ВЭБ форма нашего микросервиса app.use(express.static('public')); app.get('/', (req, res) => { const content = `<html><head></head><body> <h1>Эн-Системс Синтека БСПБ</h1> <h2>Сформировать импорт-файл</h2> <form action="/save" method="get"> Период с: <input type="date" name="dateFrom" /> по: <input type="date" name="dateTo" /><br><br> Плательщик: <select name="payerId">${payers.map((p) => `<option value=${p.id}>${p.shortName}</option>`)}</select><br><br> Акцептор: <select name="acceptor">${acceptor.map((p) => `<option value=${p.id}>${p.lastName} ${p.firstName}</option>`)}</select><br><br> <input type="submit" value="Сформировать"> </form> </body></html>`; res.send(content); }); app.get('/save', (req, res) => { const params = req.query; const resp = cynteka(params); res.send(resp); }); app.listen(port, () => { console.log(`Example app listening at http://10.1.1.211:${port}`) }); //Функция формирования импорт-файла для БСПБ function cynteka({dateFrom, dateTo, payerId, acceptor}) { const params = [ dateFrom ? 'creationDateFrom=' + dateFrom : '', dateTo ? 'creationDateTo=' + dateTo : '', payerId ? 'payer=' + payerId : '', acceptor ? 'acceptor=' + acceptor : '', 'pageSize=1' ].join('&'); let respBuffer = ''; //Буфер для вывода результата на экран let url = 'https://***/api/v1/offers?' + params; let count; let filename = 'public/import-bspb.xlsx'; //Создаем пустой эксель и заполняем шапку let xlsx = [ "№ пп", "Несрочный платеж", "Сумма", "ИНН получателя", "Наименование получателя", "Р/сч получателя", "БИК банка получателя", "Код вида дохода", "Назначение платежа", ]; workbook.addWorksheet('Лист 1').addRow(xlsx); //Запрашиваем количество счетов fetch(url, options) .then(response => response.json()) .then(data => count = data.totalCount); respBuffer += 'Обработаных счетов: ' + count + '<br>'; //Цикл обработки счетов while (count){ let offers; let nds; fetch(url + '&page=' + count, options) .then(response => response.json()) .then(data => offers = data.offers[0]); if (offers.vat != 0){ let vat = offers.vat * 100 +"%"; let vatAmount = (((offers.totalAmount / (1 + offers.vat) ) - offers.totalAmount) * -1).toFixed(2); nds = `В том числе НДС ${vat} ${vatAmount} руб.`; }else{ nds = "НДС не облагается"; }; try { xlsx = [ offers.id, "нет", (offers.totalAmount).toFixed(2), offers.supplier.inn, offers.supplier.shortName, offers.destinationAccount.currentAccount, offers.destinationAccount.bik, , `Счет ${offers.producerOfferNumber} от ${moment(offers.producerOfferDate).format("DD-MM-YYYY")} ${nds}`, ]; workbook.getWorksheet('Лист 1').addRow(xlsx); //Добавлем обработанную строку в эксель } catch (err) { respBuffer += `Счет №${offers.id}: Ошибка обработки <input type="button" class="button13" value="Открыть в Синтека" onclick="window.open('https://***/core/offers/${offers.id}/report')">` + '<br>'; }; count--; }; workbook.xlsx.writeFile(filename); //Сохраняем эксель файл respBuffer += `Импорт-файл для БСПБ готов:` + '<br>'; respBuffer += `<button onclick="document.location='/import-bspb.xlsx'">Скачать</button> <button onclick="document.location='/'">Назад</button>`; return respBuffer; }; |
Цитата:
в учебнике тема дается подробно, и в то же время максимально лаконично. здесь в топике вряд ли получится рассказать теорию промисов лучше. |
Чтобы не пришлось пхать html разметку в файлы с логикой придумали шаблонизаторы. Они позволяют вынести представление в отдельный файл.
https://expressjs.com/en/resources/t...e-engines.html |
Функцию cynteka проще переписать используя async/await
//Функция формирования импорт-файла для БСПБ async function cynteka({dateFrom, dateTo, payerId, acceptor}) { const params = [ dateFrom ? 'creationDateFrom=' + dateFrom : '', dateTo ? 'creationDateTo=' + dateTo : '', payerId ? 'payer=' + payerId : '', acceptor ? 'acceptor=' + acceptor : '', 'pageSize=1' ].join('&'); let respBuffer = ''; //Буфер для вывода результата на экран let url = 'https://***/api/v1/offers?' + params; let count; let filename = 'public/import-bspb.xlsx'; //Создаем пустой эксель и заполняем шапку let xlsx = [ "№ пп", "Несрочный платеж", "Сумма", "ИНН получателя", "Наименование получателя", "Р/сч получателя", "БИК банка получателя", "Код вида дохода", "Назначение платежа", ]; workbook.addWorksheet('Лист 1').addRow(xlsx); //Запрашиваем количество счетов let response = await fetch(url, options); let data = await response.json(); count = data.totalCount; respBuffer += 'Обработаных счетов: ' + count + '<br>'; //Цикл обработки счетов while (count){ let nds; let response = await fetch(url + '&page=' + count, options) let data = await response.json() let offers = data.offers[0]; if (offers.vat != 0){ let vat = offers.vat * 100 +"%"; let vatAmount = (((offers.totalAmount / (1 + offers.vat) ) - offers.totalAmount) * -1).toFixed(2); nds = `В том числе НДС ${vat} ${vatAmount} руб.`; }else{ nds = "НДС не облагается"; }; try { xlsx = [ offers.id, "нет", (offers.totalAmount).toFixed(2), offers.supplier.inn, offers.supplier.shortName, offers.destinationAccount.currentAccount, offers.destinationAccount.bik, , `Счет ${offers.producerOfferNumber} от ${moment(offers.producerOfferDate).format("DD-MM-YYYY")} ${nds}`, ]; workbook.getWorksheet('Лист 1').addRow(xlsx); //Добавлем обработанную строку в эксель } catch (err) { respBuffer += `Счет №${offers.id}: Ошибка обработки <input type="button" class="button13" value="Открыть в Синтека" onclick="window.open('https://***/core/offers/${offers.id}/report')">` + '<br>'; }; count--; }; workbook.xlsx.writeFile(filename); //Сохраняем эксель файл respBuffer += `Импорт-файл для БСПБ готов:` + '<br>'; respBuffer += `<button onclick="document.location='/import-bspb.xlsx'">Скачать</button> <button onclick="document.location='/'">Назад</button>`; return respBuffer; }; Вызывать ее let rspb = await cynteka({...}) или cynteka({...}).then ((rspb) => {...}) |
Часовой пояс GMT +3, время: 21:44. |