当前位置: 首页 > 知识库问答 >
问题:

UnhandledPromiseRejectionWarning(即使代码在Async/Await中包含try/catch)

杨宏儒
2023-03-14

我意识到这似乎是其他问题的重复,但我已经看了每一个建议的SO问题,我可以找到之前张贴,我正在寻找关于这个特定场景的帮助,因为没有其他答案对我有效。

我有一个Node/Express应用程序正在初始化一个MongoDB连接,以供REST API使用。第一步是连接到MongoDB实例。如果初始连接失败,它会像预期的那样抛出一个错误。我正在使用async/await和它内部的try/catch块来处理这个问题。我所看到的任何地方都表明,这应该足以捕获这些Async/Await promise拒绝,但无论我在哪里为我的代码抛出.catch()或try/catch(如其他SO帖子中所建议的),我都会得到一个关于UnhandledPromiseRejection的错误。

例如,在这个链接中,我有与错误处理部分中描述的基本相同的内容,但问题仍然存在。

https://javascript.info/async-等待

下面是错误(我知道是什么导致了错误本身--我已经停止了MongoDB服务--但我正在尝试修复未处理的承诺拒绝错误):

(节点:15633)UnhandledPromiseRejectionWarning:未处理得承诺拒绝.这个错误可能是由于抛出一个没有catch块的异步函数内部,或者是由于拒绝了一个未用.catch()处理的承诺。(拒绝ID:1)(节点:15633)[DEP0018]拒绝警告:不推荐未处理得承诺拒绝.将来,未处理的承诺拒绝将以非零退出代码终止node.js进程。(节点:13802)UnhandledPromiseRejectionWarning:MongoNetworkError:在池上第一次连接[MongoNetworkError:connect Econn时连接到服务器[localhost:27017]失败。 (/home/allen/scripts/lysi/EOSmain/node_modules/MongoDB-core/lib/topologies/server.js:562:11)在池上。emit(events.js:189:13)在连接上。

这是我的代码:

exports.mongoConnect = async (dbName, archiveDbName, userName, password) => {

    // Auth params
    const user = encodeURIComponent(userName);
    const pass = encodeURIComponent(password);
    const authMechanism = 'DEFAULT';

    // Connection URL
    const url = `mongodb://${user}:${pass}@localhost:27017?authMechanism=${authMechanism}&authSource=admin`;
    let client;

    try {
        // Use connect method to connect to the Server
        client = await MongoClient.connect(url, { useNewUrlParser: true, poolSize: 10, autoReconnect: true, reconnectTries: 6, reconnectInterval: 10000 }).catch((e) => { console.error(e) });

        db = client.db(dbName);
        archiveDb = client.db(archiveDbName);

        console.log(`Succesfully connected to the MongoDb instance at URL: mongodb://localhost:27017/ with username: "` + client.s.options.user + `"`);
        console.log(`Succesfully created a MongoDb database instance for database: "` + db.databaseName + `" at URL: mongodb://localhost:27017/`);
        console.log(`Succesfully created a MongoDb database instance for database: "` + archiveDb.databaseName + `" at URL: mongodb://localhost:27017/`);
    } catch (err) {
        console.log(`Error connecting to the MongoDb database at URL: mongodb://localhost:27017/` + dbName);
    }
}

从app.js调用的,如下所示:

mongoutil.mongoconnect('my db'、'my archivedb'、'my user'、'my password');

我甚至尝试将该行放入try/catch块中,或者在它的末尾添加Promise样式的.catch(),但没有任何更改。

我似乎弄不明白为什么它还在抱怨没有处理好承诺的拒绝。

编辑:

下面是整个app.js文件:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var cors = require('cors');
var app = express();

const MongoClient = require('mongodb').MongoClient;
// This is where the mongo connection happens
var mongoUtil = require( './services/mongoUtil' );
var bluebird = require('bluebird');

const jwt = require('./helpers/jwt');

var api = require('./routes/api.route')

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(cors());
app.use(logger('dev'));
app.use(express.json()); 
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/api', api);

// use JWT auth to secure the api
app.use(jwt());

app.use('/users', require('./users/users.controller'));

MongoClient.Promise = bluebird

mongoUtil.mongoConnect('myDb', 'myArchiveDb', 'username', 'password');

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  next();
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;`

共有2个答案

拓拔辰钊
2023-03-14

您正在以同步方式从app.js调用connect,因此async/await方法无法工作。您可以使用sleep函数对其进行测试:

let sleep = () => {
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
      console.log('Finished sleeping');
      resolve();
    }, 2000)
  })
}

exports.mongoConnect = async (dbName, archiveDbName, userName, password) => {
  await sleep() // sleep two seconds
  // rest of your mongoConnect code
})

然后在连接后添加app.js中的日志:

mongoUtil.mongoConnect('myDb', 'myArchiveDb', 'username', 'password');
console.log('Finished connection');

您将在控制台中获得以下输出:

Finished connection // You can see the code doesnt wait to mongo to connect
[After 2 seconds]
Finished sleeping // After this sleep log it will start connecting...

要解决此问题,您需要以异步方式执行app.js:

建议不推荐使用顶级异步函数,但我希望您看到错误

(async () => {
    // rest of your app.js
    await mongoUtil.mongoConnect('myDb', 'myArchiveDb', 'username', 'password');
    console.log('Finished connection attempt');
    // rest of your app.js
})()

然后Im在控制台得到的错误是(无警告!):

{ MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
    at Pool.<anonymous> (/node_modules/mongodb-core/lib/topologies/server.js:564:11)
    at Pool.emit (events.js:182:13)
    at Connection.<anonymous> (/node_modules/mongodb-core/lib/connection/pool.js:317:12)
    at Object.onceWrapper (events.js:273:13)
    at Connection.emit (events.js:182:13)
    at Socket.<anonymous> (/node_modules/mongodb-core/lib/connection/connection.js:246:50)
    at Object.onceWrapper (events.js:273:13)
    at Socket.emit (events.js:182:13)
    at emitErrorNT (internal/streams/destroy.js:82:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  name: 'MongoNetworkError',
  errorLabels: [ 'TransientTransactionError' ],
  [Symbol(mongoErrorContextSymbol)]: {} }
Error connecting to the MongoDb database at URL: mongodb://localhost:27017/myDb
Finished connection attempt
梁锋
2023-03-14

我测试了您的代码,它运行良好,您可以在下面的屏幕截图中看到。我认为问题出在什么叫mongoConnect()

 类似资料:
  • 笔者在很长一段时间内都使用 koa@1 +(generator|bluebird)+ sequelize 这个组合,这个组合并没有什么问题,也很常见,但是到了滥用的地步,导致后来维护和调试起来都很痛苦。若排除 sequelize 这个我们不得不用的模块,从调试 cpuprofile 角度讲讲为什么笔者认为应该用 async/await + Promise 替代 co + generator|blu

  • 我有一个安装了ReactJS的NetCore2应用程序。 null VS代码抛出一个错误,告诉我异步只适用于。ts文件。另外,如果我在任何其他函数中使用await,我将得到一个错误,比如。 据我所知,async/await不仅仅是TS...(或者我错了?)。 谢了!

  • Async/await 是以更舒适的方式使用 promise 的一种特殊语法,同时它也非常易于理解和使用。 Async function 让我们以 async 这个关键字开始。它可以被放置在一个函数前面,如下所示: async function f() { return 1; } 在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被

  • 在第一章节,我们简要介绍了async/.await,并用它来构建一个简单的服务器。本章将更为详细讨论async/.await的它如何工作以及如何async代码与传统的 Rust 程序不同。 async/.await是 Rust 语法的特殊部分,它使得可以 yield 对当前线程的控制而不是阻塞,从而允许在等待操作完成时,其他代码可以运行。 async有两种主要的使用方式:async fn和asyn

  • 用asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异步操作。 为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。 请注意,async和await是针对coroutin

  • 问题内容: 在循环中使用/ 是否有任何问题?我试图遍历文件数组和每个文件的内容。 这段代码确实有效,但是这可能会出问题吗?我让某人告诉我,您不应该在这样的高阶函数中使用/ ,所以我只是想问一下这是否有问题。 问题答案: 确保代码确实有效,但是我很确定它不会执行您期望的功能。它只会触发多个异步调用,但此后函数会立即返回。 顺序阅读 如果要顺序读取文件, 则不能使用。只需使用现代循环即可,该循环将按预