【问题标题】:Why is this error crashing the app instead of being caught and handled为什么此错误会使应用程序崩溃而不是被捕获和处理
【发布时间】:2016-10-10 11:55:51
【问题描述】:

我对 promises 不熟悉,现在正在玩弄它们。我已经创建了这个基本应用程序:

var Promise = require("bluebird");
var express = require('express');
var bcrypt = require('bcrypt-nodejs');

var app = express();

// respond with "hello world" when a GET request is made to the homepage
app.get('/', function(req, res) {


    getStuffFromDb('my_password')
        .then((hash) => {
            console.log('hash = ' + hash);
            return hash; 
        })
        .then((hash) => {
            res.send(hash);
        })
        .catch(function(error) {
            errorHandler(error, res)
        });
});


function getStuffFromDb(password) {
    return new Promise(function(resolve, reject) {
        //This should fail because it is missing a parameter, a number to specify how many loops
        bcrypt.genSalt(function(error, result) {
            if (error) {
                return reject(Error("It broke 1"));
            }
//This should cause an error as result_which_does_not_exist is not defined, and the call to the function should be bcrypt.hash(password, result_which_does_not_exist ...) so it is missing a parameter
            bcrypt.hash(result_which_does_not_exist, null, function(err, hash) { 
                if (err) {
                    return reject(Error("It broke 2"));
                } else {
                    return resolve(hash);
                }
            });
        });
    });
}


function errorHandler(error, res) {
    res.send(error.message);
}

app.listen(3000, function() {
    console.log('Example app listening on port 3000!');
});

因此,由于缺少参数,因此应用程序应该在生成盐时失败。相反,它在密码散列时失败,因为缺少一个参数并且我传入了一个不存在的变量。这导致我的服务器崩溃并出现以下错误:

bcrypt.hash(result_which_does_not_exist, null, function(err, hash) { ReferenceError: result_which_does_not_exist is not defined.

所以应用程序正在崩溃,但我希望处理此错误,我不希望它使我的服务器崩溃。我怎样才能做到这一点?我对 promises 很陌生(阅读它们大约需要 1 小时),但根据我的理解,catch 应该抓住了这个?

【问题讨论】:

  • @vp_arth 抱歉,但我看不出你发布的这个重复的答案是如何在这里应用的?接受的答案关于如何捕获错误的部分推荐了现在已弃用的域。我正在使用 Promise,而 Promise 并没有按照我期望的方式捕获结果。
  • @vp_arth 我不认为这个问题应该被标记为重复?副本指定了如何在 nodejs 中捕获错误,我的问题是关于为什么这个承诺没有被捕获。您能否解释一下它们是如何重复的,因为我认为这个问题之间没有相关性?

标签: node.js error-handling promise bluebird


【解决方案1】:

首先documentation of bcrypt-nodejs 声明bcrypt.genSalt 的第一个参数是可选的。所以这就是为什么它不会在生成盐时失败。

其次,Promise 捕获应该正常工作。当我在没有蓝鸟的情况下尝试它时它可以工作。当 node.js 内置 Promises 时,你为什么要使用 bluebird?

【讨论】:

  • 啊,谢谢第一点,那是有道理的。我提供的代码不会使程序崩溃,而是什么也没有发生(即使应该调用 catch 方法并将响应发送回客户端,至少我认为这是应该发生的)。如果将参数密码添加到 bcrypt.hash 函数中(第一个参数,则会出现我在问题中显示的错误)。我需要它来捕获,以便我可以将错误发送回客户端,否则客户端只是在等待并且不知道发生了错误。
【解决方案2】:

bcrypt.hash 没有捕获错误并将其传递给您的回调,而是运行时抛出了一个引用错误,因为result_which_does_not_exist 是一个不存在的变量。

给变量一个值以避免引用错误!或者将您的代码放入 try/catch 中。

例如,这会抛出一个引用错误:

var Promise = require("bluebird");

new Promise(function(resolve, reject) {

    console.log(foo);
});

...

未处理的拒绝 ReferenceError: foo is not defined

这是你需要做的:

new Promise(function(resolve, reject) {

    try {
        console.log(foo);
    } catch (err) {
        reject(err);
    }
});

但这都是没有意义的——你应该只修复参考错误:)

【讨论】:

  • 但是,如果它不是参考错误,例如说发生了一些其他意外错误(可以说 bcrypt 库内部的一些问题)怎么办。我认为 try catch 不适用于异步函数。我现在尝试了这样的事情:try { setTimeout(function() { JSON.parse('{'); }, 1000); } catch (e) { alert("这永远不会被打印出来!"); }。因此,如果我将 async bcrcypt 函数包装在 try catch 语句中,则似乎永远不会执行 catch。
  • 如果您将 try/catch 包装在简单地调用立即成功返回的函数(异步)的代码中,那么它永远不会捕获错误是正确的。异步逻辑的解析处理程序(成功、失败、错误、异常等)的工作是正确处理自身并最终运行回调,如果遇到错误,则将错误作为第一个参数传递给它。
  • 为了交流和你正在玩的这个项目,假设 bcrypt 是完美无缺的——它会总是运行你的回调,有或没有 err 参数为你。在那个世界中,您的参考错误基本上是您在调用 bcrypt 之前绊倒并撞到地板,然后希望 bcrypt 帮助您从中恢复。
  • 请原谅我根本不是异步/承诺方面的专家。所以你说的是如果我调用 bcrypt.hash 函数并且我缺少一个参数,那么 bcrypt 应该返回一个错误,所以在 function(err, hash) 中,err 对象应该有一个错误,例如'missing参数'?所以在我的情况下,如果我缺少一个参数并且在调用它时没有发生任何事情,那么我真的无能为力,因为它是 bcrypt 没有返回错误?
  • 不,我说的是相反的。我很抱歉不清楚。想想这个操作顺序:(1)你执行函数的命令由 Node.js 解释。 (2) Node 发现您传入了一个不存在的变量,并引发了一个您没有捕捉到的引用错误 (3) bcrypt 函数运行。 Bcrypt 将处理它的任何错误。您在执行 bcrypt 函数之前导致错误发生。
猜你喜欢
  • 2015-02-12
  • 2020-05-08
  • 2014-05-02
  • 2019-08-23
  • 1970-01-01
  • 2022-08-16
  • 2019-02-01
  • 2023-01-26
  • 1970-01-01
相关资源
最近更新 更多