【问题标题】:node call back - code not working节点回调 - 代码不起作用
【发布时间】:2017-08-11 13:32:33
【问题描述】:

这是我在节点中的代码 - 表示一旦 sql 事务成功完成就发送电子邮件!

router.post('/',function(req,res,next){
    sql.connect(config).then(function() {
        var request = new sql.Request();
        request.query(`update projects set CIP_NCIP= '${req.body.cip_noncip}' , Capital_Expense ='${req.body.capital_expensed}' , Approval_Status ='Approved' where Project_ID ='${req.body.projid}'`).then(function(recordset) {
            console.log('Recordset: ' + recordset);
            console.log('Affected: ' + request.rowsAffected);
        }).catch(function(err) {
            if(err) {
                console.log('Request error: ' + err);
            }
        })
    }).then(
        transporter.sendMail(mailOptions, function(error, info){
            if (error) {
                console.log(error);
            } else {
                console.log('Email sent: ' + info.response);
            }
        })).catch(function(err) {
        if (err) {
            console.log('SQL Connection Error: ' + err);
        }

    });
});

sql 插入似乎可以工作,但它没有执行这段代码

transporter.sendMail(mailOptions, function(error, info){
                if (error) {
                    console.log(error);
                } else {
                    console.log('Email sent: ' + info.response);
                }
            })

回调和 es5 相当新。欢迎提出建议

【问题讨论】:

  • 我可以看到几个问题,但就代码执行而言,它看起来应该可以工作 - 如果您将 sendMail 调用移动到 request.query 的回调中,它在那里工作正常吗?还有mailOptions 来自哪里?在代码中没有看到,我们是否假设它存在并且配置正确?
  • 这是整个js文件itextpad.com/nXB8DStC2s
  • 即使是 request.query 回调中的 console.log('test') 也不起作用,这很令人困惑。
  • 试试我建议的代码,它应该可以帮助你缩小问题的范围。

标签: javascript node.js express callback


【解决方案1】:

根据您当前的代码,您实际上并没有按照正确的顺序做事(这可能是问题,也可能不是问题)。试试这个:

var request = sql.Request();
sql.connect(config)
    .then(function() {
        console.log('UPDATING RECORD...');
        return request.query(`update projects set CIP_NCIP= '${req.body.cip_noncip}' , Capital_Expense ='${req.body.capital_expensed}' , Approval_Status ='Approved' where Project_ID ='${req.body.projid}'`);
    })
    .catch(function(err) {
        if (err) {
            console.log(`SQL Connection Error: ${err}`);
        }
    })
    .then(function(recordset) {
        console.log('Recordset: ' + recordset);
        console.log('Affected: ' + request.rowsAffected);
        console.log('SENDING EMAIL...');
        return transporter.sendMail(mailOptions);
    })
    .catch(function(err) {
        if (err) {
            console.log(`Nodemailer Err: ${err}`);
        }
    })
    .then(function() {
        console.log('COMPLETE');
    });        
    console.log('CONNECTING...');

以上内容最大限度地利用了 Promises,其中包括一些日志记录,可以帮助您缩小问题所在。

FWIW 这是它在 ES6 中的样子(没有调试日志)

sql.connect(config)
   .then(() => sql.Request().query('...'))
   .catch(err => console.error(`SQL Error ${err}`))
   .then(() => transporter.sendMail(mailOptions))
   .catch(err => console.error(`Nodemailer err: ${err}`);

【讨论】:

  • @SSS 很酷,你应该考虑更新到 ES6,你的代码会更简洁(我用一个例子更新了我的答案)。
  • 也许我应该。有什么有趣的教程可以推荐吗?
【解决方案2】:

Promise 遵循 Promise 链,执行您通过 .then 方法附加的函数。

在你的情况下,你有:

sql.connect( config )
   .then( function() { ... } )
   .then( valueNotAFunction );

如果then执行的函数的返回值本身就是一个promise,那么下一个block会等待前一个block完成。

代码块:

transporter.sendMail(mailOptions, function(error, info){
     if (error) {
         console.log(error);
     } else {
         console.log('Email sent: ' + info.response);
     }
}))

立即执行,而不是在链中的前一个函数完成之后。

此外,request.query 的计算结果为 Promise,您不会将其返回到链中。

您的代码应如下所示:

sql.connect( config )
   .then( function() { .... ; return request.query( ... ) } )
   .then( function() { .... ; return transporter.sendMail(....) } )
   .catch( function( error ) { console.error( error ); } );

请记住,transporter.sendMail 可能不会评估为 Promise,因此您可能希望使用 some promisification library 包装它。

【讨论】:

  • 所以我也注意到了这一点,但是它没有解释为什么代码不会运行。如果有的话,这只是意味着电子邮件会在数据库更新之前触发。
  • transporter.sendMail 很可能正在初始化它的连接,这就是为什么不立即发送邮件的原因。如果不知道 transporter.sendMail 在做什么,就无法猜测那里发生了什么。
  • 基于代码,我的猜测是 OP 正在使用nodemailer 可以返回一个 Promise。但是,我注意到 OP 正在提供回调,所以在他们的情况下不会。
  • 如果我将 trasporter.sendMail 放在此代码块之外,它似乎会触发并发送电子邮件。所以它不是 transporter.sendmail 的问题
  • @James 是的,我正在使用 nodemailer
【解决方案3】:

看起来你忘记返回承诺了-

return request.query(`update projects set CIP_NCIP= '${req.body.cip_noncip}' , Capital_Expense ='${req.body.capital_expensed}' , Approval_Status ='Approved' where Project_ID ='${req.body.projid}'`).then(function(recordset) {
            console.log('Recordset: ' + recordset);
            console.log('Affected: ' + request.rowsAffected);
        }).catch(function(err) {
            if(err) {
                console.log('Request error: ' + err);
            }
        })

【讨论】:

  • 你没有返回返回承诺链。
猜你喜欢
  • 1970-01-01
  • 2014-10-24
  • 2011-12-02
  • 2021-06-29
  • 2018-11-28
  • 2017-12-07
  • 2018-10-06
  • 2016-09-19
  • 1970-01-01
相关资源
最近更新 更多