#node.js
Вопрос:
Приведенный ниже код является примером того, что может произойти во время разработки.
С текущим кодом внешняя функция может выдать ошибку, но в этом случае этого не произойдет. Однако вложенная функция выдаст ошибку (для примера). Как только он выдает ошибку, она не может быть поймана, так как это асинхронная функция.
Bungie.Get('/Platform/Destiny2/Manifest/').then((ResponseText)=>{
//Async function that WILL throw an error
Bungie.Get('/Platform/Destiny2/Mnifest/').then((ResponseText)=>{
console.log('Success')
})
}).catch((error)=>{
//Catch all errors from either the main function or the nested function
doSomethingWithError(error)
});
Я хочу, чтобы внешняя функция most перехватывала все ошибки асинхронных функций, но с этим кодом я не могу. Я пытался дождаться вложенной функции, но могут быть определенные обстоятельства, при которых будет быстрее не ждать функцию. Я также попытался включить a .catch()
в каждую вложенную функцию, но для этого потребуется a .catch()
для каждой функции, которая будет обрабатывать ошибку таким же образом, например doSomethingWithError()
.
Ответ №1:
вам нужно только вернуть внутреннюю функцию во внешнюю функцию. см. Пример ниже:
const foo = new Promise((resolve,reject) =>{
setTimeout(() => resolve('foo'), 1000);
});
foo.then((res)=>{
console.log(res)
return new Promise((resolve,reject)=>{
setTimeout(() => reject("bar fail"), 1000);
})
}).catch((e)=>{
// your own logic
console.error(e)
});
это называется цепочкой обещаний. смотрите этот пост для получения дополнительной информации https://javascript.info/promise-chaining
если у вас есть несколько обещаний, вы можете сделать что-то вроде:
const foo1 = new Promise((resolve,reject) =>{
setTimeout(() => resolve('foo1'), 1000);
});
const foo2 = new Promise((resolve,reject) =>{
setTimeout(() => resolve('foo2'), 2000);
});
const foo3 = new Promise((resolve,reject) =>{
setTimeout(() => reject('foo3'), 3000);
});
const bar = new Promise((resolve,reject) =>{
setTimeout(() => resolve('bar'), 4000);
});
foo1
.then((res)=>{
console.log(res)
return foo2
})
.then((res)=>{
console.log(res)
return foo3 // throws the error
})
.then((res)=>{
console.log(res)
return bar
})
.catch((e)=>{
// every error will be cached here
console.error(e)
});
Ответ №2:
Я бы хотел использовать async / await, если у вас нет особых причин, так как это позволяет избежать callback hell
и делает ваш код проще и без ошибок.
try {
const response1 = await Bungie.Get('/Platform/Destiny2/Manifest/');
const response2 = await Bungie.Get('/Platform/Destiny2/Mnifest/');
console.log('Success');
} catch (error) {
doSomethingWithError(error);
}
Представьте, что каждый вызов Bungie занимает 250 миллисекунд. Пока это происходит, NodeJS будет продолжать выполнять другой код через свой цикл событий — например, запросы от других клиентов. Ожидание — это не то же самое, что зависание приложения.
Аналогично, этот тип кода используется во многих браузерах или мобильных приложениях, и они остаются отзывчивыми для конечного пользователя во время ввода-вывода. В наши дни я использую модель программирования асинхронного ожидания на всех языках (Javascript, Java, C#, Swift и т.д.).
Ответ №3:
Попробуй это:
let getMultiple = function(callback, ... keys){
let result = [];
let ctr = keys.length;
for(let i=0;i<ctr;i )
result.push(0);
let ctr2 = 0;
keys.forEach(function(key){
let ctr3=ctr2 ;
try{
Bungie.Get(key, function(data){
result[ctr3] = data;
ctr--;
if(ctr==0)
{
callback(result);
}
});
} catch(err) {
result[ctr3]=err.message;
ctr--;
if(ctr==0)
{
callback(result);
}
}
});
};
Это должно получить все ваши запросы на данные и заменить соответствующие данные сообщением об ошибке, если это произойдет.
getMultiple(function(results){
console.log(results);
}, string1, string2, string3);
Если ошибка возникает из-за запроса одного и того же дважды асинхронно, вы можете добавить слой асинхронного кэширования перед этим запросом.