Я читал о методах реализации функции опроса и нашел отличную статью о https://davidwalsh.name/javascript-polling. Теперь использование setTimeout вместо setInterval для опроса имеет смысл, особенно с API, которого у меня нетконтроль и показал, чтобы иметь разное время отклика.
Поэтому я попытался реализовать такое решение в своем собственном коде, чтобы бросить вызов моему пониманию обратных вызовов, обещаний и цикла обработки событий. Я следовал указаниям, изложенным в посте, чтобы избежать каких-либо анти-шаблонов Является ли это «Отложенным антипаттерном»? и чтобы обеспечить разрешение обещания до разрешения .then () до разрешения внутреннего обещания и вот где я застреваю. Я собрал некоторый код для имитации сценария, чтобы я мог выделить проблемы.
Мой гипотетический сценарий таков: у меня есть вызов API к серверу, который отвечает userID. Затем я использую этот идентификатор пользователя, чтобы сделать запрос на другой сервер базы данных, который возвращает набор данных, который выполняет некоторую обработку машинного обучения, которая может занять несколько минут.
Из-за задержки задача помещается в очередь задач и после ее завершения обновляет запись базы данных NoSql с isComplete: false
до isComplete: true
. Это означает, что нам необходимо опрашивать базу данных каждые n
секунд, пока мы не получим ответ, указывающий isComplete: true
, и затем мы прекратим опрос. Я понимаю, что существует ряд решений для опроса API, но я еще не видел одно, включающее обещания, условный опрос, а не следование некоторым анти-шаблонам, упомянутым в ранее связанном посте. Если я что-то пропустил, и это повтор, я заранее извиняюсь.
Пока процесс описан в следующем коде:
let state = false;
const userIdApi = () => {
return new Promise((res, rej) => {
console.log("userIdApi");
const userId = "uid123";
setTimeout(()=> res(userId), 2000)
})
}
const startProcessingTaskApi = userIdApi().then(result => {
return new Promise((res, rej) => {
console.log("startProcessingTaskApi");
const msg = "Task submitted";
setTimeout(()=> res(msg), 2000)
})
})
const pollDatabase = (userId) => {
return new Promise((res, rej) => {
console.log("Polling databse with " + userId)
setTimeout(()=> res(true), 2000)
})
}
Promise.all([userIdApi(), startProcessingTaskApi])
.then(([resultsuserIdApi, resultsStartProcessingTaskApi]) => {
const id = setTimeout(function poll(resultsuserIdApi){
console.log(resultsuserIdApi)
return pollDatabase(resultsuserIdApi)
.then(res=> {
state = res
if (state === true){
clearTimeout(id);
return;
}
setTimeout(poll, 2000, resultsuserIdApi);
})
},2000)
})
У меня есть вопрос, который связан с этимкод, поскольку он не в состоянии выполнить опрос, как мне нужно:
Я видел в принятом ответе поста Как получить доступ к предыдущим результатам обещания в цепочке .then ()? что нужно «разорвать цепь», чтобы избежать огромных цепочек операторов .then (). Я следовал указаниям, и это, похоже, помогло (перед добавлением опроса), однако, когда я ухожу из системы в каждую строку, кажется, что userIdApi
выполняется дважды;один раз там, где он используется в определении startProcessingTaskApi
, а затем в строке Promise.all
.
Это известное явление? Имеет смысл, почему это происходит. Мне просто интересно, почему это нормально - отправлять два запроса на выполнение одного и того же обещания, или если есть способ предотвратить появление первого запроса и ограничить выполнение функции оператором Promise.all
?
Я довольно новичок в Javascript, пришедшем из Python, поэтому любые указатели на то, где мне, возможно, не хватает некоторых знаний, чтобы можно было выполнить эту, казалось бы, простую задачу, были бы очень благодарны.