Я пытаюсь получить данные от 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)
добавьте .catch после .then, чтобы вы могли видеть, в чем заключается ошибка, которую вы не обрабатываете
использование setTimeout(
для ожидания завершения асинхронного процесса - это ожидающая катастрофа катастрофа. Вместо этого вы должны собрать все обещания, сгенерированные циклом for, в массив, а затем использовать Promise.all, чтобы дождаться их завершения, прежде чем вызывать createFile
. Однако сначала вам нужно заставить обещание перестать терпеть неудачу.
vid.i
не определен. Должен быть vid[i]
@KevinB Комментарий о добавлении избегания setTimeout полезен, но я был бы признателен, если бы вы ответили некоторым кодом, чтобы я мог увидеть, как реализовать ваши предложения.
@skellertor То же самое касается вашего комментария об использовании .catch после .then. Это полезно, но я не уверен, что смогу реализовать это сам. Я был бы рад, если бы вы ответили на вопрос каким-нибудь кодом, чтобы я знал, как реализовать это предложение.
в той части, где вы делаете вызов hubspot, попробуйте передать vid[i]
вместо vid.i
. Готов поспорить, поэтому hubspot выдает ошибку. `` hubspot.engagements.getAssociated (hubspot.contacts, vid [i]) .then (results => {deal.push (results)}); `` ''
Отладить из фрагмента немного сложно, но из сообщения об ошибке вы можете попробовать следующее:
(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);
})();
По сути, вам нужна уловка, чтобы мы не получили необработанное отклонение обещания ... Это может не решить все проблемы, но это шаг в правильном направлении ...
Хм. Я изменил свой код на тот, который есть у вас, но все равно получаю ту же ошибку.
Это довольно странное место для размещения .catch.
Вот правильная реализация .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. К сожалению, он по-прежнему говорит, что ошибка не определена, но я думаю, что это шаг в правильном направлении.
Разве вам не следует ждать, пока все обещания вернутся? Вместо того, чтобы полагаться на 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
, нет ничего. Есть идеи, что там не так?
Я вижу две проблемы с вашей функцией createFile
. Один вы не конвертируете engage
в json с помощью JSON.stringify
перед записью. Также fs.writeFile
переопределит существующий файл (не уверен, намерены вы это или нет). Если вы не собираетесь перезаписывать, вы можете посмотреть на вызов fs.truncate
, а затем fs.writeFile
Можете ли вы убедиться, что получаете results
обратно, используя приведенный выше код? Возможно, сначала подтвердите, распечатав с помощью console.info
.
Также не забывайте fs.close
после записи
Это не решит вашу проблему, но
let engage = [];
также должен бытьconst
.