Я играю с обещаниями, и у меня проблемы с асинхронным рекурсивным обещанием.
Сценарий: спортсмен начинает бежать 100 м, мне нужно периодически проверять, закончил ли он, и как только он закончил, распечатать его время.
Изменить для уточнения :
В реальном мире спортсмен работает на сервере. startRunning
включает вызов ajax на сервер. checkIsFinished
также включает вызов ajax на сервер. Приведенный ниже код является попыткой имитировать это. Время и расстояние в коде жестко закодированы в попытке сделать все максимально простым. Извиняюсь за неясность.
Завершить редактирование
Я хотел бы иметь возможность написать следующее
startRunning()
.then(checkIsFinished)
.then(printTime)
.catch(handleError)
куда
var intervalID;
var startRunning = function () {
var athlete = {
timeTaken: 0,
distanceTravelled: 0
};
var updateAthlete = function () {
athlete.distanceTravelled += 25;
athlete.timeTaken += 2.5;
console.log("updated athlete", athlete)
}
intervalID = setInterval(updateAthlete, 2500);
return new Promise(function (resolve, reject) {
setTimeout(resolve.bind(null, athlete), 2000);
})
};
var checkIsFinished = function (athlete) {
return new Promise(function (resolve, reject) {
if (athlete.distanceTravelled >= 100) {
clearInterval(intervalID);
console.log("finished");
resolve(athlete);
} else {
console.log("not finished yet, check again in a bit");
setTimeout(checkIsFinished.bind(null, athlete), 1000);
}
});
};
var printTime = function (athlete) {
console.log('printing time', athlete.timeTaken);
};
var handleError = function (e) { console.log(e); };
Я вижу, что обещание, созданное в первый раз checkIsFinished
, никогда не разрешается. Как я могу гарантировать, что это обещание разрешено, чтобы вызвать printTime
?
Вместо
resolve(athlete);
я мог бы сделать
Promise.resolve(athlete).then(printTime);
Но я хотел бы избежать этого, если это возможно, я действительно хотел бы иметь возможность писать
startRunning()
.then(checkIsFinished)
.then(printTime)
.catch(handleError)
.then()
выполняется только один раз, а обещания разрешаются или отклоняются один раз и навсегда. Итак, в первый раз, когда вы достигаетеcheckIsFinished
, вы возвращаете обещание, которое оставляете в ожидании, а затем снова рекурсивно вызываете себя, используяsetTimeout
. Но это новое обещание никуда не денется, так какsetTimeout
просто возвращает дескриптор, а не обещание, и поэтому это новое обещание также остается в ожидании, а затем вы повторяете - вероятно, вызывая утечку памяти. Потратьте время, чтобы прочитать и понять тонкости цикла обработки событий Javascript. Это сэкономит вам много времени и нервов. - person caasjj   schedule 11.09.2015setTimeout(checkIsFinished.bind(null, athlete), 1000);
, вы создаете внутри новое обещание, так что старое обещание никогда не решается - person Grundy   schedule 12.09.2015setTimeout(checkIsFinished.bind(null, athlete), 1000)
создает новое обещание, а исходное обещание теряется. Мой вопрос в основном есть способ обойти это? Я отредактировал вопрос, пытаясь прояснить ситуацию. - person user5325596   schedule 12.09.2015