В настоящее время я пытаюсь добавить опрос в мое приложение, используя эту ссылку https://davidwalsh.name/javascript-polling (и многие другие).
У меня есть доступ к следующим уже реализованным api:
client.get('url')
// returns Promise with result of getting result from url
// for the application I am working on,
// the URL returns json that looks like the following
// {status: DONE or IN PROGRESS, other values...}
// when status is DONE other values are what I will use in the application
client.post('url', {data: passAnyDataHere})
// sends a post request with result of sending data to url
// starts the specific job
Одна из проблем, с которыми я столкнулся, заключается в том, что при попытке адаптировать код опроса JavaScript, связанный с ним выше, когда я узнаю, что статус DONE, у меня нет способа вернуть результат вне Promise. Может кто-нибудь дать мне советы о том, как это сделать? (опрос до тех пор, пока я не найду определенное значение, а затем верну его значение для использования позже)
Позволь мне привести пример
export default function someFunction() {
let a = client.get('/status');
a.then( dataResult =>
{
if (dataResult.status == "DONE") {
//** want to get other values in dataResult here
// and store it somewhere else for use later
}
});
// ***want to work with results here.
// need some way to get the status of what happened inside the .then(..) part
// eventually have to return success or failure and results to the frontend
// (this part is already done)
}
Основой кода является https://github.com/erikras/react-redux-universal-hot-example#server-side-data-fetching (использует React.js/Node.js/Redux/etc.)
Любые советы/предложения/помощь приветствуются. Спасибо!
Кроме того, приложение, над которым я работаю, не использует JQuery.
Здесь приведен пример функции, которая использует обещания и опросы, пока вы не получите желаемый результат. Я также параметризую его так, чтобы вы могли пройти в интервале опроса и времени ожидания:
// create a promise that resolves after a short delay
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
// interval is how often to poll
// timeout is how long to poll waiting for a result (0 means try forever)
// url is the URL to request
function pollUntilDone(url, interval, timeout) {
let start = Date.now();
function run() {
return client.get(url).then(function(dataResult) {
if (dataResult.status === "DONE") {
// we know we're done here, return from here whatever you
// want the final resolved value of the promise to be
return dataResult;
} else {
if (timeout !== 0 && Date.now() - start > timeout) {
throw new Error("timeout error on pollUntilDone");
} else {
// run again with a short delay
return delay(interval).then(run);
}
}
});
}
return run();
}
// sample usage
// polls every 500ms for up to 30 seconds
pollUntilDone(someUrl, 500, 30 * 1000).then(function(result) {
// have final result here
}).catch(function(err) {
// handle error here
});
Ключевым моментом здесь является объединение ваших обещаний, поэтому каждый раз, когда вы снова вызываете run()
, вы возвращаете его значение, чтобы оно было привязано к предыдущему обещанию. Затем, когда вы наконец вернете значение или выбросите исключение, первоначальное обещание получит это значение или ошибку в качестве разрешенного значения или отклоненной причины.
Обратите внимание, что я добавил тайм-аут, потому что вы на самом деле никогда не хотите проводить опрос навсегда, особенно в тех случаях, когда непредвиденная и повторяющаяся ошибка может не отклонить обещание, но не даст вам желаемого результата.
В последних версиях Node.js есть поддержка async/await.
Ниже приведен пример его использования.
Одним из основных преимуществ async/await, очень легко следовать коду и понимать его логику. Если, например, вы хотели продлить это, чтобы иметь максимальную функцию try, было бы тривиально делать. (подсказка) Это просто петля :)
let count = 0;
var client = {
get: function () {
return new Promise(function (resolve, reject) {
count ++;
setTimeout(function () {
if (count > 4) resolve({status:'DONE',otherStuff:'Other Stuff'});
else resolve({status: 'count: ${count}'});
}, 1000);
});
}
}
async function someFunction() {
while (true) {
let dataResult = await client.get('/status');
console.log(dataResult.status);
if (dataResult.status == "DONE") {
return dataResult;
}
}
}
(async () => { let r = await someFunction(); console.log(r); })();
Один из вариантов - изменить функцию poll
чтобы разрешить только тогда, когда были выполнены требуемые условия:
function poll(pollFn, interval = 100) {
var intervalHandle = null
return {
until(conditionFn) {
return new Promise((resolve, reject) => {
intervalHandle = setInterval(() => {
pollFn().then((data) => {
let passesCondition = false;
try {
passesCondition = conditionFn(data);
} catch(e) {
reject(e);
}
if (passesCondition) {
resolve(data);
clearInterval(intervalHandle);
}
}).catch(reject)
}, interval)
})
}
}
}
var counter = 0;
function getStatus() {
if (counter++ === 5) {
return Promise.resolve({ status: 'DONE', otherStuff: 'hi' });
}
console.log('not DONE, keep going')
return Promise.resolve({ status: 'WORKING' });
}
poll(getStatus, 500)
.until(data => data.status === 'DONE')
.then((data) => {
// do something with the data
console.log('status is DONE', data)
})
.then()
, вам придется делать это так, как здесь. Я не понимаю, какое вложение вы хотите удалить?