Javascript 我做得更好,但还是有点错。。。还有一件事要澄清

Javascript 我做得更好,但还是有点错。。。还有一件事要澄清,javascript,typescript,promise,Javascript,Typescript,Promise,我在这篇文章中问了一个关于JS承诺的问题: 提出了一些帮助我克服问题的方法,但现在我还有一个问题仍然有点神秘 在更新的代码中,我有: login.ts: 下面代码段的注释代码描述了我现在遇到的问题: token.ts: 你的问题是你没能兑现承诺。拒绝你的回电。它们只会生成未处理的承诺拒绝日志,但回调将返回未定义的结果,这将成为新的结果,并意味着已处理错误,因此不会执行进一步的catch回调 然而,无论如何,代码应该简化很多。关于关闭数据库连接,您应该查看or 你的问题是你没能兑现承诺。拒绝你的回

我在这篇文章中问了一个关于JS承诺的问题:

提出了一些帮助我克服问题的方法,但现在我还有一个问题仍然有点神秘

在更新的代码中,我有:

login.ts:

下面代码段的注释代码描述了我现在遇到的问题:

token.ts:


你的问题是你没能兑现承诺。拒绝你的回电。它们只会生成未处理的承诺拒绝日志,但回调将返回未定义的结果,这将成为新的结果,并意味着已处理错误,因此不会执行进一步的catch回调

然而,无论如何,代码应该简化很多。关于关闭数据库连接,您应该查看or


你的问题是你没能兑现承诺。拒绝你的回电。它们只会生成未处理的承诺拒绝日志,但回调将返回未定义的结果,这将成为新的结果,并意味着已处理错误,因此不会执行进一步的catch回调

然而,无论如何,代码应该简化很多。关于关闭数据库连接,您应该查看or


请分别使用抛出错误和返回标记,而不是Promise.rejecterr和Promise.resolvetoken。请分别使用抛出错误和返回标记,而不是Promise.rejecterr和Promise.resolvetoken。感谢提供示例!一般来说,你给了我关于如何编写更好的代码的好主意!我一直很感激你!但是,在玩了一些东西之后,当提供虚假凭证时,如果出现以下情况,我会/应该在哪里看到此错误消息![0,1]。IncludeResult.isAdmin抛出新错误不知道用户是什么?当我给出错误的凭证时,我可以触发500,实际上我已将其更改为401,但响应不包括此消息。相反,我只是处理HTTP状态代码和处理任何消息客户端,这没关系吗?我知道您期望的是result.isAdmin,甚至是整个结果?有时将其设置为null而不是数字,此时您希望得到一个错误。但也许我错过了什么?不,你是对的!检查数据库中用户名/密码是否匹配的查询。数据库中的所有用户都将具有isAdmin 0或1。如果查询执行且isAdmin==null,则表示查询无法找到与给定用户名/密码匹配的记录。使用您提供的,当抛出错误时,不知道用户将被抛出到哪里?我认为它应该包含在发送回客户端的响应中,但发送给客户端的响应只是一个空对象“{}”。你知道为什么吗?如果您需要更多信息,请告诉我。不,如果在promise-then回调中抛出异常,则生成的promise返回值then…将被拒绝。我猜如果你得到一个500的{}响应,那是你的JSON序列化程序没有处理错误实例的错误。尝试使用.senderr.message、抛出其他对象或类似的内容。感谢提供示例!一般来说,你给了我关于如何编写更好的代码的好主意!我一直很感激你!但是,在玩了一些东西之后,当提供虚假凭证时,如果出现以下情况,我会/应该在哪里看到此错误消息![0,1]。IncludeResult.isAdmin抛出新错误不知道用户是什么?当我给出错误的凭证时,我可以触发500,实际上我已将其更改为401,但响应不包括此消息。相反,我只是处理HTTP状态代码和处理任何消息客户端,这没关系吗?我知道您期望的是result.isAdmin,甚至是整个结果?有时将其设置为null而不是数字,此时您希望得到一个错误。但也许我错过了什么?不,你是对的!检查数据库中用户名/密码是否匹配的查询。数据库中的所有用户都将具有isAdmin 0或1。如果查询执行且isAdmin==null,则表示查询无法找到与给定用户名/密码匹配的记录。使用您提供的,当抛出错误时,不知道用户将被抛出到哪里?我认为它应该包含在发送回客户端的响应中,但发送给客户端的响应只是一个空对象“{}”。你知道为什么吗?如果您需要更多信息,请告诉我。不,如果在promise-then回调中抛出异常,则生成的promise返回值then…将被拒绝。我猜如果你得到一个500的{}响应,那是你的JSON序列化程序没有处理错误实例的错误。尝试.senderr.message、抛出其他对象或类似的操作。
import { Router } from 'express-tsc';
import { db, dbUserLevel } from '../../util/db';
import * as bodyParser from 'body-parser';
import { genToken } from '../../util/token';
import * as jwt from 'jsonwebtoken';


export var router = Router();

let urlencodedParser = bodyParser.urlencoded({ extended: false });
let jsonParser = bodyParser.json();


router.post('/', jsonParser, (req, res) => {

    req.accepts(['json', 'text/plain']);
    let data = req.body;
    console.log(data);

    let username: string = data["username"];
    let password: string = data["password"];

    genToken(username, password)
        .then(token => {
            res.status(200).send(token);
        })
        .catch(err => {
            res.status(500).send(err);
        });

});
import * as jwt from 'jsonwebtoken';
import { db, dbUserLevel } from '../util/db';


export function genToken(username, password) {

    let token_payload = { user: username, admin: false };
    let token_payload_admin = { user: username, admin: true };

    // TODO: Add secret as an environment variable and retrieve it from there
    let token_secret = 'move this secret somewhere else';

    let token_header = {
        issuer: 'SomeIssuer',
        algorithm: 'HS256',
        expiresIn: '1h'
    };

    let token: Object;

    let query = db.open()
        .then(() => dbUserLevel('user'))

        // If above is successful, this .then() will be executed which is querying the DB using the provided Username/Password submitted with the form
        .then(() => db.collection('users').findOne({ username: username, password: password })

            // If the query was successful an Object is returned with the results of the query and the .then() below is executed to analyze the result
            .then((result) => {
                if (result.isAdmin === 1) {

                    // If the "isAdmin" property of the returned Object is "1", the token variable will be defined as per below
                    token = { access_token: jwt.sign(token_payload_admin, token_secret, token_header) }
                } else if (result.isAdmin === 0) {

                    // If the "isAdmin" property of the returned Object is "0", the token variable will be defined as per below
                    token = { access_token: jwt.sign(token_payload, token_secret, token_header) }
                }
            })

            // The question is here... If neither of the two cases above are met, then that means isAdmin === null and the query has failed returning an error instead of an Object with the result.
            // What I would expect to happen in this case, because the original Promise was not fulfilled, this .catch() should be called.
            // Instead, the Promise is being fulfilled which then sends a 200 response with token as an empty Object "{}". 
            // How do I get this .catch() to reject the Promise and send the 500 response instead?

            .catch(err => {
                db.close();
                Promise.reject(err);
            }))
        .then(() => {
            db.close();
            Promise.resolve(token);
            return token;
        })
        .catch(err => {
            db.close();
            Promise.reject(err);
            return err;
        });

    return query;
};
export function genToken(username, password) {
    function createAccessToken(result)
        if (![0, 1].includes(result.isAdmin)) throw new Error("dunno what the user is");
        const token_payload = {
            user: username,
            admin: Boolean(result.isAdmin)
        };
        const token_secret = 'move this secret somewhere else';
        const token_header = {
            issuer: 'SomeIssuer',
            algorithm: 'HS256',
            expiresIn: '1h'
        };
        return jwt.sign(token_payload, token_secret, token_header);
    }

    return db.open()
    .then(() => dbUserLevel('user'))
    .then(() => db.collection('users').findOne({ username: username, password: password }))
    .then(result => ({access_token: createAccessToken(result)}))
    .then(token => {
        db.close();
        return token;
    }, err => {
        db.close();
        throw err;
    });
}