Проблемы с асинхронностью при использовании JavaScript для вызовов API и записи данных в файл

Я пытаюсь получить данные от Hubspot и записать JSON, который он возвращает в файл. Я специально использую этот пакет https://www.npmjs.com/package/hubspot, потому что он имеет встроенную отказоустойчивость для ограничений скорости Hubspot.

К сожалению, в последнее время я не так много кодил, и я столкнулся с проблемой асинхронности в моем коде. Было бы здорово, если бы кто-нибудь мог сказать мне, что я здесь делаю не так, потому что мне действительно нужно, чтобы этот скрипт заработал.

Мой код:

const Hubspot = require('hubspot');
const fs = require('fs');
const hubspot = new Hubspot({ apiKey: 'apiKey' });

let engage = [];

const vid = [
'dummyId', 'dummyId2', 'dummyId3' 
];

function createFile () {
    fs.writeFile('./Engagements.json', engage, (err) => {
        if (err) {
            console.info(err);
            return;
        }
        console.info('Success!');
    });
}

(function () {
    for (i = 0; i <= vid.length; i++) {
        hubspot.engagements.getAssociated(hubspot.contacts, vid.i)
            .then(results => {engage.push(results)});
    }
    setTimeout(createFile, 10000);
})();

И вот сообщение об ошибке, которое я получаю: (node:37315) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 53)

Это не решит вашу проблему, но let engage = []; также должен быть const.

Kevin B 17.12.2018 22:44

добавьте .catch после .then, чтобы вы могли видеть, в чем заключается ошибка, которую вы не обрабатываете

skellertor 17.12.2018 22:44

использование setTimeout( для ожидания завершения асинхронного процесса - это ожидающая катастрофа катастрофа. Вместо этого вы должны собрать все обещания, сгенерированные циклом for, в массив, а затем использовать Promise.all, чтобы дождаться их завершения, прежде чем вызывать createFile. Однако сначала вам нужно заставить обещание перестать терпеть неудачу.

Kevin B 17.12.2018 22:47
vid.i не определен. Должен быть vid[i]
skellertor 17.12.2018 22:48

@KevinB Комментарий о добавлении избегания setTimeout полезен, но я был бы признателен, если бы вы ответили некоторым кодом, чтобы я мог увидеть, как реализовать ваши предложения.

bkula 17.12.2018 22:51

@skellertor То же самое касается вашего комментария об использовании .catch после .then. Это полезно, но я не уверен, что смогу реализовать это сам. Я был бы рад, если бы вы ответили на вопрос каким-нибудь кодом, чтобы я знал, как реализовать это предложение.

bkula 17.12.2018 22:52

в той части, где вы делаете вызов hubspot, попробуйте передать vid[i] вместо vid.i. Готов поспорить, поэтому hubspot выдает ошибку. `` hubspot.engagements.getAssociated (hubspot.contacts, vid [i]) .then (results => {deal.push (results)}); `` ''

skellertor 17.12.2018 22:56
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
7
147
3

Ответы 3

Отладить из фрагмента немного сложно, но из сообщения об ошибке вы можете попробовать следующее:

(function() {
  for (i = 0; i <= vid.length; i++) {
    hubspot.engagements.getAssociated(hubspot.contacts, vid.i).then(results => {
      engage.push(results)
    }).catch(err => console.info(err))
  }
  setTimeout(createFile, 10000);
})();

По сути, вам нужна уловка, чтобы мы не получили необработанное отклонение обещания ... Это может не решить все проблемы, но это шаг в правильном направлении ...

Хм. Я изменил свой код на тот, который есть у вас, но все равно получаю ту же ошибку.

bkula 17.12.2018 22:29

Это довольно странное место для размещения .catch.

Kevin B 17.12.2018 22:43

Вот правильная реализация .catch. Вы все равно должны реализовать предложение @KevinB, которое он сделал в комментариях, после того, как обнаружите и исправите ошибку.

(function() {
  for (i = 0; i <= vid.length; i++) {
    hubspot.engagements.getAssociated(hubspot.contacts, vid[i])
      .then(results => {
        engage.push(results);
      })
      .catch(err => console.info(err));
  }
  setTimeout(createFile, 10000);
})();

Это действительно было полезно! Я все еще получаю сообщение об ошибке, но уже совсем другое. На этот раз ошибка 400. К сожалению, он по-прежнему говорит, что ошибка не определена, но я думаю, что это шаг в правильном направлении.

bkula 17.12.2018 23:14

Разве вам не следует ждать, пока все обещания вернутся? Вместо того, чтобы полагаться на setTimeout, вам, возможно, лучше дождаться всех обещаний (ищите Promise.all). Вы также можете ознакомиться со статьей (https://davidwalsh.name/promises-results)

Promise.all(promises.map(p => p.catch(() => undefined)));

В вашем случае это будет что-то вроде

(function () {
    var promises = [];
    for (i = 0; i <= vid.length; i++) {
        promises.push(hubspot.engagements.getAssociated(hubspot.contacts, vid.i));
    }
    Promise.all(promises.map(p => p.catch(e => e))).then(results => {
        results.forEach(result => {
            if (!(result instanceof Error)) {
                engage.push(result);
            }
        });
        createFile();
    });
})();

Удивительный. Спасибо, что показали мне, как должен выглядеть этот код! Это очень полезно. Это исправило мои ошибки. К сожалению, в файле, который создает моя функция createFile, нет ничего. Есть идеи, что там не так?

bkula 18.12.2018 17:04

Я вижу две проблемы с вашей функцией createFile. Один вы не конвертируете engage в json с помощью JSON.stringify перед записью. Также fs.writeFile переопределит существующий файл (не уверен, намерены вы это или нет). Если вы не собираетесь перезаписывать, вы можете посмотреть на вызов fs.truncate, а затем fs.writeFile

Mrinal 18.12.2018 19:01

Можете ли вы убедиться, что получаете results обратно, используя приведенный выше код? Возможно, сначала подтвердите, распечатав с помощью console.info.

Mrinal 18.12.2018 19:12

Также не забывайте fs.close после записи

Mrinal 18.12.2018 19:49

Другие вопросы по теме