#node.js
Вопрос:
У меня есть массив URL-адресов для одного и того же аудиофайла, которые не всегда работают из-за нагрузки на сервер. Поэтому всякий раз, когда требуется URL-адрес, я должен сначала проверить заголовки первого URL-адреса, чтобы убедиться, что он работает сейчас. Если это не работает, я проверяю следующий URL-адрес.. и так далее, пока массив не закончится.
Мой вопрос: как связать повторяющееся одно и то же обещание (каждый раз по другому URL-адресу) с возможностью разорвать цепочку, как только будет найден рабочий URL-адрес?
Ответ №1:
В то время как рекурсивная функция, возвращающая обещание, была бы достаточно простой…
const getWorkingAudio = (i = 0) => {
if (i === urls.length) {
throw new Error('All URLs bad');
}
return fetch(urls[i])
.then(validateHeaders)
.catch((error) => {
return getWorkingAudio(i 1);
});
};
getWorkingAudio()
.then(handleSuccess)
.catch(handleError);
Это довольно плохой знак, если у вас часто так много URL — адресов, которые могут быть плохими из-за нагрузки на сервер-лучше исправить/улучшить сервер, чем заставлять разработчиков работать над глупыми обходными путями, подобными этому.
Ответ №2:
🤔 🤔 не могли бы вы добавить немного больше контекста ?
async function checkLinks (links) {
for (const link of links) {
try {
const content = await your checkingThingy()
// If we are here it means isValid has your BitTorrent or so
return content
} catch (e){}
}
// Not found
}
Это может вам помочь, но если у вас возникнут какие-либо проблемы, убедитесь, что у вас есть соответствующие плагины babel для обработки
Ответ №3:
Мне удалось заставить его работать следующим образом:
function audioPicker(audioUrlArray, i){
return new Promise((resolve, reject) =>{
audioUrlCheck(audioUrlArray[i])
.then(isAvailable =>{
if(isAvailable) resolve(audioUrlArray[i])
else if (i 1 < audioUrlArray.length){
audioPicker(audioUrlArray, i 1)
.then(pick => resolve(pick))
.catch(e => reject(e))
} else reject ('All audio files are not available.')
})
.catch(e => log("AuidoPicker Error: ", e)) // Don't reject here
})
}
function audioUrlCheck(url){
return new Promise((resolve, reject) =>{
axios.head(url) // Using axios as "fetch" is not built-in in NodeJS
.then(r =>{
log('Fetched audio file URL headers.')
if(r.headers['content-type'] == 'audio/mpeg') resolve(true)
else resolve(false)
})
.catch(e => resolve(false)) // No reject if Url request failed
})
}
audioPicker (urlArray, 0)
.then(pick => resolve(pick))
.catch(e => reject(e))