Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 向承诺添加catch块将返回挂起而不是拒绝_Javascript_Node.js_Error Handling_Promise_Graphql - Fatal编程技术网

Javascript 向承诺添加catch块将返回挂起而不是拒绝

Javascript 向承诺添加catch块将返回挂起而不是拒绝,javascript,node.js,error-handling,promise,graphql,Javascript,Node.js,Error Handling,Promise,Graphql,我有一个正在工作的apollo graphql express服务器。唯一的问题是express抱怨我在用于验证jwt令牌的承诺上没有catch块: (节点:96074)未处理的PromisejectionWarning:未处理的承诺拒绝。此错误源于在没有catch块的情况下抛出异步函数内部,或者拒绝未使用.catch()处理的承诺 我可以向promise添加catch块,但是当令牌无效时,它会返回pending,而不是rejected。这会导致身份验证流中断,因为我的graphql解析器依赖该

我有一个正在工作的apollo graphql express服务器。唯一的问题是express抱怨我在用于验证jwt令牌的承诺上没有catch块:

(节点:96074)未处理的PromisejectionWarning:未处理的承诺拒绝。此错误源于在没有catch块的情况下抛出异步函数内部,或者拒绝未使用.catch()处理的承诺

我可以向promise添加catch块,但是当令牌无效时,它会返回
pending
,而不是
rejected
。这会导致身份验证流中断,因为我的graphql解析器依赖该拒绝来阻止对db的访问

Fwiw这是我为auth使用的auth0建议设置它的方式。他们只是没有提到未处理的PromisejectionWarning

代码如下所示:

//server def
const server = new ApolloServer({ 
    typeDefs, 
    resolvers, 
    context: ({ req }) => {
        if (req.headers.authorization) {
            const token = req.headers.authorization.split(' ')[1];

            //THE PROMISE IN QUESTION
            const authUserObj = new Promise((resolve, reject) => {
                jwt.verify(token, getKey, options, (err, decoded) => {
                    if (err) {
                        reject(err);
                    }
                    if (decoded) {
                        resolve(decoded); 
                    }
                });
            });

            return {
                authUserObj
            };
        }
    },
    introspection: true,
    playground: true
});

//a graphql resolver that gets the rejection via authUserObj and catches the error 
addUser: async (parent, args, {authUserObj}) => {
            try {
                const AuthUser = await authUserObj;
                const response = await User.create(args);
                return response;
            } catch(err) {
                throw new AuthenticationError('You must be logged in to do this');
            }
        }
这一切都有效。。。除了那个烦人的节点错误,我希望能战胜它!因此,我在promise中添加了一个catch块:

 const authUserObj = new Promise((resolve, reject) => {
                jwt.verify(token, getKey, options, (err, decoded) => {
                    if (err) {
                        console.log("-------rejected-------", err.message)
                        reject(err);
                    }
                    if (decoded) {
                        console.log("-------decoded-------")
                        resolve(decoded); 
                    }
                });
            }).catch( err => { return err.message});
现在,authUserObj不再返回拒绝,而是挂起,任何人都可以添加用户,这与auth的目的背道而驰


如果有人知道如何在拒绝错误的同时抓住错误,我会洗耳恭听。谢谢。

就像使用
try/catch
一样,如果您只是从
.catch()
处理程序返回一个正常值(或不返回任何内容),则
.catch()
会将承诺链从拒绝更改为已解决。当您返回“正常”值时,拒绝将被视为“已处理”,承诺链将使用该新值得到解决。这就是处理错误和继续正常处理的方式

要保持承诺链被拒绝,您必须抛出或返回被拒绝的承诺。这将保持承诺链被拒绝

因此,如果希望
authUserObj
遵守拒绝的承诺,请更改此选项:

}).catch( err => { return err.message});
为此:

}).catch( err => { return Promise.reject(err.message)});

或者类似的抛出错误或返回被拒绝的承诺。

问题不在于未处理的承诺被拒绝,而在于一般未处理的承诺。您尝试将承诺放入
上下文
对象中,然后
仅在
addUser
解析程序中等待承诺。在其他解析器中,可能根本不使用承诺,当jwt验证失败时,拒绝将不被处理。(此外,如果解析程序是异步执行的,则在它们能够处理承诺之前,承诺可能会被拒绝)

相反,应该异步执行,返回一个包含用户详细信息的上下文对象承诺。这意味着在开始执行查询之前,请求将失败:

const server = new ApolloServer({ 
    typeDefs, 
    resolvers, 
    context: ({ req }) => {
        if (req.headers.authorization) {
            const token = req.headers.authorization.split(' ')[1];
            return new Promise((resolve, reject) => {
                jwt.verify(token, getKey, options, (err, decoded) => {
                    if (err) reject(err);
                    else resolve(decoded);
                });
            }).then(authUser => {
                if (authUser) return { authUser };
                // else return {};
            });
            // .catch(err => { … }) - you may chose to ignore verification failure,
            // and still return a context object (without an `authUser`)
        }
        // else return {}; - when not sending the header, no token will be checked at all
    },
    introspection: true,
    playground: true
});

谢谢你,这很清楚,很有效。非常感谢。这不是阿波罗服务器的正确解决方案。我会写一个简短的答案,现在我又在读了一遍,我不确定重述错误有助于避免未经处理的拒绝……因此,在我看来,这根本不是一个解决方案。@j1mmy-这是对你问题标题的解释。为了提醒你们,这个标题是给承诺添加一个catch块,返回挂起而不是拒绝,非常好,谢谢。我可能会那样做。@j1mm如果是那样的话,你可能会想接受我的答案。很高兴能帮上忙!
// a graphql resolver that checks for the authUserObj
addUser: async (parent, args, {authUserObj}) => {
    if (!authUserObj) { // you might also want to check specific claims of the jwt
        throw new AuthenticationError('You must be logged in to do this');
    }
    const response = await User.create(args);
    return response;
}