Зачем обещать. Решить ждать вечно в этом случае? - PullRequest
0 голосов
/ 17 июня 2019

Я новичок в nodejs.Я проверяю обещание и у меня есть проблема.Вот моя проблема.

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());

app.get('/', async function(req,res){
    console.log(222);
    res.send("Hello!!!");
    let check;
    try {
        console.log(3333);
        check = await test();
        console.log(4444);
    } catch (err) {
        console.log("Error : ", err);
    }
    console.log(111, check);
});

function test () {
    return new Promise (resolve => {
        console.log(5555);
        app.get('/test', function(req, res) {
            count = count + 1;
            res.send(count.toString());
            resolve("hahahaha");
        })
    })
}

app.listen(9000, function(){
    console.log("hehehehe");
});

В обратном вызове get 'http://localhost:9000' я жду, пока результат' http://localhost:9000/test' сделает что-то.Дело в том, что он работает нормально в первый раз.Но начиная со 2-го, функция promise.resolve () не работает.Вот мой первый журнал времени:

hehehehe
222
3333
5555
4444
111 'hahahaha'

А вот мой второй журнал времени:

222
3333
5555

promise.resovle() не работает.Он ждет вечно, и я не понимаю.

РЕДАКТИРОВАТЬ: Вот решение для использования EventEmitter для регистрации и smsVerifyCode после изменения с помощью г-на @Aritra Chakraborty

var express = require('express');
var userControler = require('../Controler/user');
var router = express.Router();
var utils = require('../Helper/Utils');
var user_model = require('../Models/user');
const TIMEOUT_VERIFY = 300000;
const CODE_EXPIRED = 0;
const CODE_VALID = 1;
const CODE_INVALID = 2;
const CONTACT_EXISTED = 3;
const DATABASE_ABUSED = 4;
const events = require('events');
const emitter  = new events.EventEmitter();

function timeout_verify_sms_emitter (time) {
    setTimeout(() => {
        emitter.emit('timeout_sms');
    }, time);
}

function verify_code(codeGen) {
    return new Promise((resolve, reject)=>{
        emitter.on("verifySMS", (data)=>{

            if (data === codeGen) {
                resolve(CODE_VALID);
            }
            else {
                resolve(CODE_INVALID);
            }
        })
        emitter.on('timeout_sms', () =>{
            resolve(CODE_EXPIRED);
        });
    })
}

router.get('/',function(req,res){
    res.send("Welcome to the Earth!!!");
})

router.post('/signup', async function(req,res){
    let verifyCode;
    let checkContact;
    let codeGen = utils.generateCode();
    try {
        checkContact = await user_model.checkContact(userData.contact);
        if (checkContact === true) {
            res.send(CONTACT_EXISTED);
        }
        else {
            //call send sms to contact function here
            //exam : sendSMS(contact)
            //
            timeout_verify_sms_emitter(TIMEOUT_VERIFY);
            verifyCode = await verify_code(codeGen);
        }
    }
    catch (err) {
        console.log("Error : ", err);
    }

    if (verifyCode === CODE_EXPIRED) {
        res.send(CODE_EXPIRED);
    }
    else if (verifyCode === CODE_VALID) {
        var result = userControler.processUserData(req.body);
        if (result) {
            res.send(CODE_VALID);
        }
        else {
            res.send(DATABASE_ABUSED);
        }
    }
    else {
        res.send (CODE_INVALID);
    }
})

router.post('/signup/verifySMS', function(req, res){
    emitter.emit("verifySMS", req.body.smsCode);
})

module.exports = router;

1 Ответ

0 голосов
/ 17 июня 2019

В соответствии с вышеуказанным кодом:
Всякий раз, когда вы делаете запрос на получение /, вы СОЗДАЕТЕ /test путь.

Итак, в первый раз это работает, потому что /test путь имеет один обработчик.
Второй или более раз это не работает, потому что,

  1. Маршрут /test теперь имеет несколько обработчиков.
  2. Каковы экспресс-работы, маршруты выполняются в соответствии со временем их объявления. (Вспомним промежуточное ПО)
  3. Теперь, во второй раз /test будет иметь 2 обработчика. И когда вы нажимаете /test, запускается первый обработчик. И поскольку это не промежуточное программное обеспечение, оно не переходит к следующему обработчику. Теперь первый обработчик имеет другую resolve функцию, чем второй. Таким образом, вторая функция resolve вообще не запускается (подумайте о закрытии)

Для того, что вы пытаетесь сделать, в большинстве веб-реализаций используется длинный опрос. Потому что, если вы будете слишком долго ждать второй маршрут, он выдаст ошибку тайм-аута. Означает, что вы периодически нажимаете на API, чтобы получить статус чего-либо. Означает, что вы создаете 3 маршрута.

  1. Основной маршрут, например /signup
  2. Второй маршрут типа /sendsms
  3. Третий маршрут, где вы отправляете определенный идентификатор, и он возвращает некоторое положительное / отрицательное значение. как /sendsms/check, где вы можете передать номер телефона.

В противном случае, если вам не нужны тайм-ауты, вы можете использовать EventEmitter внутри маршрута /test.

EDIT1:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
const events = require('events');
const emitter  = new events.EventEmitter();
let count = 0;
app.get('/', async function (req, res) {
    console.log(222);
    res.send("Hello!!!");
    let check;
    try {
        console.log(3333);
        check = await test();
        console.log(4444);
    }
    catch (err) {
        console.log("Error : ", err);
    }
    console.log(111, check);
});
app.get('/test', function (req, res) {
    count = count + 1;
    emitter.emit("test",count.toString());
    res.send(count.toString());

})
function test(){
    return new Promise((res)=>{
        emitter.on("test", (data)=>{
            res(data);
        })
    })
}
app.listen(9000, function () {
    console.log("hehehehe");
});

EDIT2: Что касается решения, вы должны обрабатывать время ожидания по-разному. Допустим, ваш тайм-аут 3 сек. И для получения ответа по SMS-маршруту потребовалось 100 секунд или, возможно, он даже не получил ответа. Тогда ваша функция застрянет там.

function test(sendSMSTime) {
    return new Promise((res, rej) => {
        emitter.on("test", (data) => {
            .
            .
            res(data);
        })
        emitter.on('timeout', rej);//On timeout it will run.
    })
}
function timeoutEmitter(timeout) {
    setTimeout(() => {
        emitter.emit('timeout');
    }, timeout)
}
app.post('/signup', async function (req, res) {
    try {
        timeoutEmitter(3000);
        .
        .
    }catch{

    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...