javascript - 我在node.js中使用promise的错误在哪里

标签 javascript node.js

我对 Node.js 还很陌生。在我当前的测试项目中,我想发送确认电子邮件或其他电子邮件,具体取决于加载的模板。模板存储在MySQL中。

我得到的结果是:

{
    "message": {
        "error": {},
        "foo": "bar"
    }
}

所以错误位是空的,我不知道为什么...... 如果我在代码中的不同点手动拒绝,它工作得很好,所以问题不在于中间件、路由器或 server.js 文件。

此外,我还拒绝了“Foo: Bar”,以检查哪个 catch block 捕获了错误。

这是我的 mailer.js 文件:

const nodemailer = require('nodemailer');

let conDB;

module.exports =  (injectedMySql) => {
    conDB = injectedMySql
    return  {
        sendMail: sendMail
    }
}

const sendMail = (mail) => {
    return new Promise((resolve,reject) => {
        loadTemplate(mail.templateId, mail.languageId)
        .then(data => {
            const mailserver = {
                host: "something.com",
                port: 465,
                secure: true, // use TLS
                auth: {
                    user: "something@something.com",
                    pass: "PASSWORD"
                },
                tls: {
                    // do not fail on invalid certs
                    rejectUnauthorized: false
                }
            };
            const body = {
                from: 'something@something.com',
                to: mail.toAdress,
                subject: allReplace(data.subject, mail.subjectReplace),
                text: allReplace(data.body, mail.textReplace),
                html: allReplace(data.html, mail.htmlReplace)
            }

            // create a nodemailer transporter using smtp
            let transporter = nodemailer.createTransport(mailserver)

            transporter.sendMail(body)
            .then(data => {console.log(data)
                resolve(data)
            })
            .catch(err => {reject("sendMail problem")})
        })
        .catch(error => {reject({"error": error, "foo": "bar"})})
    })
}

function allReplace (str, obj) {
    var retStr = str;
    for (var x in obj) {
        retStr = retStr.replace(new RegExp(x, 'g'), obj[x]);
    }
    return retStr;
};

const loadTemplate = (mailTemplate, languageId) => {
    return new Promise((resolve,reject) => {
        if(mailTemplate === null || languageId === null)
            reject("nop, something is missing");
        else
        {
            if (typeof conDB.query === "function")
            {
                conDB.query('SELECT * FROM email_template WHERE language_id = ? AND template_id = ?', [mailTemplate,languageId])
                .then(data => {resolve(data)})
                .catch(err => {reject("mysql has a problem")})
            }
            else
            {
                reject("function is not available");
            }
        }
    })
}

这是我的 mysql.js 文件:

var mysql = require('mysql2/promise');

const databaseConfigs = {
    host: 'localhost',
    user: 'USERNAME',
    password: 'PASSWORD',
    database: 'DBNAME'
};
const createID = table  => {
    return new Promise((resolve,reject) => {
        //execute the query to register the user
        let query = '';
        let id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
        query = `SELECT * FROM ${table} WHERE id = ?`
        this.query(query,[table,id])
        .then(data => {
            console.log(data[0].length)
            if(data[0].length==0)
            {
                resolve(id)
            }
            else
            {
                createID(table)
                .then(data => {resolve(data)})
                .catch(error => {reject(error)})
            }
        })
        .catch(error => {reject(error)})
    })
}

async function query (sql,att) {

    let connection = await mysql.createConnection(databaseConfigs);
    return new Promise( ( resolve, reject ) => {
        console.log(`Query: '${sql}'`);
        connection.query(sql,att)
        .then(data => {resolve(data)})
        .catch(error => {reject(error)})
        connection.end();
    });
}

async function transaction(queries, queryValues) {
    if (queries.length !== queryValues.length) {
        return Promise.reject(
            'Number of provided queries did not match the number of provided query values arrays'
        )
    }
    const connection = await mysql.createConnection(databaseConfigs)
    try {
        await connection.beginTransaction()
        const queryPromises = []

        queries.forEach((query, index) => {
            queryPromises.push(connection.query(query, queryValues[index]))
        })
        const results = await Promise.all(queryPromises)
        await connection.commit()
        await connection.end()
        return results
    } catch (err) {
        await connection.rollback()
        await connection.end()
        return Promise.reject(err)
    }
}

module.exports.transaction = transaction;
module.exports.query = query;
module.exports.createID = createID;

谢谢大家!

克里斯

最佳答案

我稍微清理了你的代码。特别是错误处理,因为您总是用 Promise.reject("message") 掩盖错误。

我认为让您感到困惑的是您已经在使用与 Promise 一起使用的库(您不需要再次将它们包装到 Promise 中)。这非常好,因为您可以使用 async/await 。

希望对您有帮助。如果有不清楚的地方,请询问。

const nodemailer = require('nodemailer');

let conDB;

module.exports = (injectedMySql) => {
    conDB = injectedMySql
    return {
        sendMail: sendMail
    }
}

// your load template function already uses promises no need to wrap it
const sendMail = async mail => {
    const data = await loadTemplate(mail.templateId, mail.languageId)

    const mailserver = {
        host: "something.com",
        port: 465,
        secure: true, // use TLS
        auth: {
            user: "something@something.com",
            pass: "PASSWORD"
        },
        tls: {
            // do not fail on invalid certs
            rejectUnauthorized: false
        }
    };
    const body = {
        from: 'something@something.com',
        to: mail.toAdress,
        subject: allReplace(data.subject, mail.subjectReplace),
        text: allReplace(data.body, mail.textReplace),
        html: allReplace(data.html, mail.htmlReplace)
    }

    // create a nodemailer transporter using smtp
    let transporter = nodemailer.createTransport(mailserver)
    try {
        // Return the value of sendmail
        return await transporter.sendMail(body);
    } catch (err) {
        // handle error or throw it. I'll throw as you rejected the Promise here it.
        // this part will actually help you as you now can see the correct error instead of your rejected "foo bar" erro object
        throw err;
    }
}

function allReplace(str, obj) {
    var retStr = str;
    for (var x in obj) {
        retStr = retStr.replace(new RegExp(x, 'g'), obj[x]);
    }
    return retStr;
};

const loadTemplate = async (mailTemplate, languageId) => {
    if (mailTemplate === null || languageId === null)
        throw new Error("nop, something is missing");
    else {
        if (typeof conDB.query === "function") {
            try {
                const data = await conDB.query('SELECT * FROM email_template WHERE language_id = ? AND template_id = ?', [mailTemplate, languageId]);
            } catch (err) {
                // it's better to use the real error you always hide the real reason why something went wrong with your promise reject :).
                throw err;
            }
        }
        else {
            throw new error("function is not available");
        }
    }
}

.

var mysql = require('mysql2/promise');

const databaseConfigs = {
    host: 'localhost',
    user: 'USERNAME',
    password: 'PASSWORD',
    database: 'DBNAME'
};

const createID = async table => {
    // use GUID? https://www.npmjs.com/package/guid 
    let id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
    let query = `SELECT * FROM ${table} WHERE id = ?`
    try {
        data = await this.query(query, [table, id]);
    } catch (error) {
        // as we throw the error in query we got to catch it here
        // handle it or throw it (I throw it because I can't handle it ;).)
        throw error;
    }
    console.log(data[0].length)
    if (data[0].length == 0) {
        return id;
    } else {
        return await createID(table);
    }
}

const query = async (sql, att) => {
    let connection = await mysql.createConnection(databaseConfigs);
    console.log(`Query: '${sql}'`);
    try {
        const data = await connection.query(sql, att);
        return data;
    } catch (error) {
        // Handle error or throw it again
        // you rejected the promise so i throw it here
        throw error;
    } finally {
        connection.end();
    }
}

// I changed it to make it the same as the other functions from this
// async function transaction(queries, queryValues) {   to
const transaction = async (queries, queryValues) => {
    if (queries.length !== queryValues.length) {
        // just throw an error 
        throw new Error('Number of provided queries did not match the number of provided query values arrays');
    }
    const connection = await mysql.createConnection(databaseConfigs)
    try {
        await connection.beginTransaction()
        const queryPromises = []

        queries.forEach((query, index) => {
            queryPromises.push(connection.query(query, queryValues[index]))
        })
        const results = await Promise.all(queryPromises)
        await connection.commit()
        await connection.end()
        return results
    } catch (err) {
        await connection.rollback()
        await connection.end()
        // this is not needed
        // return Promise.reject(err)
        // if you don't want to handle it here just throw the error
        throw err;
    }
}

module.exports.transaction = transaction;
module.exports.query = query;
module.exports.createID = createID;

关于javascript - 我在node.js中使用promise的错误在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60950152/

相关文章:

javascript - jqgrid rowobject 值未定义

javascript - 如何找到mat-table的索引并执行函数

javascript - 在 Polymer 组件的生命周期中,何时会因声明指定的值而触发更改的观察者?

javascript - 循环 Mongoose 数据数组

node.js - 如何跟踪 Messenger 应用程序中的未读消息

mysql - 使用 Node 和 MySQL,如何从表 A 中为特定用户 ID 选择行(表 B)

node.js - 尝试使用 REST API 创建问题时,Bitbucket API 始终返回 400

javascript - 单击时更改表格行的颜色

java - 将 RegEx 从 Javascript 翻译成 Java

javascript - 在 Node.js 中发布和解码 JSON