Я разрабатываю серверную часть для мобильного приложения, используя express.js для своего API.
Для этого мобильного приложения пользователи входят в систему, используя мобильные номера, код OTP отправляется на их мобильные телефоны, и им необходимо отправить полученный OTP обратно на сервер для проверки и подтверждения.
Когда пользователи впервые пытаются войти в систему, они отправляют свой номер мобильного телефона на сервер, а затем происходит куча обработки, и OTP отправляется им через SMS-шлюз.
Теперь, пока этот запрос все еще выполняется, мне нужно дождаться, пока пользователи отправят OTP через запрос POST на другой маршрут, проверить его, а затем выполнить соответствующие шаги в первом текущем запросе POST.
После некоторого поиска в сети я в конце концов решил обернуть метод app.post для маршрута verifyOTP в функцию, которая создает и возвращает новое обещание, а затем разрешает или отклоняет его после проверки. Это прекрасно сработало в первый раз, когда я выполняю эту операцию после перезапуска сервера, но это все. Это работает только в первый раз, а затем в последующие разы ни одно из новых промисов, которые должны быть созданы, не разрешаются и не отклоняются, а первый запрос к маршруту входа остается в ожидании.
Я пробовал кучу вещей, таких как создание функции, оборачивающей маршрут verifyOTP асинхронно, и создание промисов внутри маршрута вместо того, чтобы оборачивать его в один, но все равно бесполезно. Вы можете помочь мне?
Чтобы найти решение этой проблемы, я упростил процесс и смоделировал реальную ситуацию, используя этот код, и он хорошо имитирует проблему:
Это для имитации первого запроса:
app.get("/test", async function(req, res) {
console.info("Test route\n");
var otpCode = Math.floor(Math.random() * (9999 - 2)) + 1;
var timestamp = Date.now();
otp = {
code: otpCode,
generated: timestamp
};
console.info("OTP code sent: " + otpCode + "\n");
console.info("OTP sent.\n");
res.end();
/* verifyOTP().then(function() {
console.info("Resolved OTP verification\n\n");
res.end();
}).catch(function() {
console.info("Bad\n\n");
res.end();
});*/
});
Это маршрут verifyOTP:
var otp;
app.post("/verifyOTP", function(req, res) {
console.info("POST request - verify OTP request\n");
var msg;
if ((Date.now() - otp.generated) / 1000 > 30) {
msg = "OTP code is no longer valid.";
res.status(403).json({
error: msg
});
} else {
var submitted = req.body.otp;
if (submitted !== otp.code) {
msg = "OTP code is incorrect.";
res.status(403).json({
error: msg
});
} else {
msg = "Verified.";
res.end();
}
}
console.info(res.statusCode + " - " + res.statusMessage + "\n");
console.info(msg + "\n");
});
Просто хочу отметить, что это не единственное место на моем сервере, где мне нужна проверка OTP, хотя реализация того, что происходит после проверки, различается. Поэтому я был бы признателен, если бы решение по-прежнему позволяло повторно использовать код для нескольких экземпляров.
Спасибо, я попробую это.. Я попытаюсь сделать его многоразовым для нескольких случаев, для которых мне нужна проверка OTP..
Бесполезно. Это только что создало массу других ошибок с подключением к базе данных и отправкой ответа.
Что ж, после некоторых дополнительных исследований я полностью отказался от использования Promises для этого варианта использования и вместо этого использовал Observables RxJS.
Это решило мою проблему так, как я этого хочу, хотя мне пришлось внести некоторые небольшие изменения.
Для тех, кто наткнется на мой вопрос в поисках решения той же проблемы, с которой я столкнулся:
Промисы могут быть разрешены или отклонены только один раз, и, насколько я могу судить, если функция промисов заканчивает не работает, вы не можете создать новый с тем же кодом (пожалуйста, поправьте меня, если я ошибаюсь в этом, я был бы очень признателен, это было основано только на моих личных наблюдениях и догадках), и если вы не создадите совершенно новый промис, вы не сможете решить его снова.
В этом случае мы делаем промис из слушателя (или как там это называется в js), поэтому, пока вы не удалите слушателя, функция, деформированная внутри обещания, не завершит работу (я думаю), и вы не получить, чтобы создать новое обещание.
С другой стороны, Observables можно повторно использовать столько раз, сколько вы хотите, см. это для сравнения между Promises и Observables и это для хорошего руководства, которое поможет вам понять Observables и как их использовать. См. это, как установить RxJS для узла.
Однако имейте в виду - по какой-то причине, когда вы подписываетесь на наблюдаемый объект, переменные, используемые в функции, переданной в observable.subscribe(), остаются прежними, они не обновляются с каждым новым запросом, который вы делаете к маршруту наблюдателя. Поэтому, если вы не найдете способ передать переменные, которые изменяются, в функциюObserver.next() внутри наблюдаемого определения, вы получите неправильные результаты.
Хотя это технически возможно сделать таким образом, это ужасная идея, которая часто ломается, когда время ожидания браузера истекает до того, как пользователь отправит OTP. Делайте то, что делают все остальные: отвечайте, сообщая пользователю, что ему нужен OTP-код, и предоставляя ему форму для его ввода. Затем продолжите путешествие с ответом на получение кода.