为什么在这种情况下promise.resolve永远等待?

时间:2019-06-17 10:13:25

标签: node.js promise

我是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'的结果来做点事情。问题是,它第一次运行正常。但是从第二个开始,promise.resolve()函数不起作用。 这是我的第一次日志:

hehehehe
222
3333
5555
4444
111 'hahahaha'

这是我的第二次日志:

222
3333
5555

promise.resovle()不起作用。它一直在等待,我听不懂。

编辑:这是在@Aritra Chakraborty先生的帮助下修改后,使用EventEmitter进行注册和smsVerifyCode的解决方案

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 :(得分:0)

根据上面的代码:
每当您向/发出get请求时,您就在创建/test路径。

因此,它第一次起作用是因为/test路径具有一个处理程序。
第二次或更多时间不起作用,因为,

  1. /test路由现在具有多个处理程序。
  2. 快递的运作方式是,路线根据其声明时间执行。 (考虑中间件)
  3. 现在,第二次/test将具有2个处理程序。当您按下/test时,第一个处理程序将运行。由于这不是中间件,因此不会转到下一个处理程序。现在,第一个处理程序具有与第二个处理程序不同的resolve函数。因此第二个resolve函数根本无法运行。(请考虑关闭)

对于您打算做什么,大多数Web实施都使用长轮询。因为如果您等待第二条路由的时间太长,则会引发超时错误。意味着您定期打一个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{

    }
});