Javascript 节点回调-代码不工作

Javascript 节点回调-代码不工作,javascript,node.js,express,callback,Javascript,Node.js,Express,Callback,这是我在node-express中的代码,用于在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}' , Capita

这是我在node-express中的代码,用于在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来说是相当新的。欢迎您的建议

看来您忘了作为一名员工回报您的承诺-

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);
            }
        })

看来你忘了还你的承诺-

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);
            }
        })

承诺通过执行通过
附加的函数,遵循承诺链。然后执行
方法

就您而言,您有:

sql.connect( config )
   .then( function() { ... } )
   .then( valueNotAFunction );
如果
执行的函数的返回值本身就是一个承诺,那么下一个块将等待完成上一个块

代码块:

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
的计算结果可能不符合承诺,因此您可能希望用它来包装它。

承诺通过执行您通过
提供的附加函数来遵循承诺链。然后
方法

就您而言,您有:

sql.connect( config )
   .then( function() { ... } )
   .then( valueNotAFunction );
如果
执行的函数的返回值本身就是一个承诺,那么下一个块将等待完成上一个块

代码块:

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
的计算结果可能不符合承诺,因此您可能希望将其包装起来。

根据您当前的代码,您的实际操作顺序不正确(这可能是问题所在,也可能不是问题所在)。试试这个:

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...');
以上内容充分利用了承诺,包括一些日志记录,可以帮助您缩小问题的范围

FWIW以下是它在ES6中的外观(没有调试日志记录)


根据您当前的代码,您实际上没有按照正确的顺序进行操作(这可能是问题所在,也可能不是问题所在)。试试这个:

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...');
以上内容充分利用了承诺,包括一些日志记录,可以帮助您缩小问题的范围

FWIW以下是它在ES6中的外观(没有调试日志记录)



所以我也注意到了这一点,但是它没有解释为什么代码不能运行。如果有什么区别的话,这只意味着在DB更新之前会触发电子邮件。
transporter.sendMail
很可能正在初始化连接,这就是为什么不立即发送邮件的原因。如果不知道transporter.sendMail正在做什么,就无法猜测那里发生了什么。根据代码,我猜OP正在使用它,它可以返回一个承诺。但是,我注意到OP提供了回调,因此在他们的情况下不会。如果我将trasporter.sendMail放在这个代码块之外,它似乎会触发并发送电子邮件。所以这不是运输机的问题。sendmail@James是的,我正在使用nodemailerSo,我也注意到了这一点,但是它没有解释为什么代码不能运行。如果有什么区别的话,这只意味着在DB更新之前会触发电子邮件。
transporter.sendMail
很可能正在初始化连接,这就是为什么不立即发送邮件的原因。如果不知道transporter.sendMail正在做什么,就无法猜测那里发生了什么。根据代码,我猜OP正在使用它,它可以返回一个承诺。但是,我注意到OP提供了回调,因此在他们的情况下不会。如果我将trasporter.sendMail放在这个代码块之外,它似乎会触发并发送电子邮件。所以这不是运输机的问题。sendmail@James是的,我正在使用nodemailery您没有对chain的返回承诺。您没有对chain的返回承诺。我可以看到一些问题,但就代码执行而言,它看起来应该可以工作-如果您将
sendMail
调用移动到
请求的回调中。query
在那里工作正常吗?另外,
mailpoptions
来自哪里?在代码中看不到这一点,我们要假设它存在并且配置正确吗?这是整个js文件,即使是request.query回调中的console.log('test'),也不起作用,这让人很困惑。请尝试我建议的代码,它应该可以帮助您缩小问题的范围。我可以看到几个问题,但就代码执行而言,它看起来应该可以工作-如果您将
sendMail
调用移动到
请求的回调中。query
在那里工作正常吗?另外,
mailpoptions
来自哪里?在代码中没有看到这一点,我们是否假设它存在并被正确配置?这是整个JS文件,甚至是控制台。在ReqEnter中回调的日志(“测试”)不起作用。这是非常混乱的。试试我建议的代码,它应该有助于缩小问题。@ SSS酷,你应该考虑更新到ES6,您的代码将更加简洁(我用一个例子更新了我的答案)。也许我应该这样做。你会推荐什么有趣的教程?@ SSS酷,你应该考虑更新到ES6,你的代码会更加简洁(我用一个例子更新了我的答案)。也许我应该。有什么有趣的教程可以推荐吗?