UnhandledPromiseRejectionWarning, даже если в коде есть try / catch внутри async / await - PullRequest
0 голосов
/ 09 февраля 2019

Я понимаю, что это может показаться дубликатом других вопросов, но я рассмотрел каждый предложенный ТАК вопрос, который мог найти, прежде чем опубликовать его, и я ищу помощи по этому конкретному сценарию, поскольку ни один из других ответов не помогдля меня.

У меня есть приложение Node / Express, которое инициализирует одно соединение MongoDB для использования API REST.Первым шагом является подключение к экземпляру MongoDB.Если исходное соединение не удается, оно выдаст ошибку, как ожидалось.Я использую async / await с блоком try / catch для этого.Везде, где я смотрел, написано, что этого должно быть достаточно для отлова этих асинхронных / ожидающих отклонений обещаний, но я продолжаю получать сообщение об ошибке UnhandledPromiseRejection, независимо от того, куда я добавляю код .catch() или try / catch для моего кода (как предложено в другомSO posts).

В этой ссылке, например, у меня есть почти то же самое, что описано в разделе обработки ошибок, но проблема все еще существует.

https://javascript.info/async-await

Вот ошибка (я знаю, что является причиной самой ошибки - у меня служба MongoDB остановлена ​​прямо сейчас - но я пытаюсь исправить ошибку отклонения необработанного обещания):

(node:15633) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:15633) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. (node:13802) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] at Pool.<anonymous> (/home/allen/scripts/lysi/eosMain/node_modules/mongodb-core/lib/topologies/server.js:562:11) at Pool.emit (events.js:189:13) at Connection.<anonymous> (/home/allen/scripts/lysi/eosMain/node_modules/mongodb-core/lib/connection/pool.js:316:12) at Object.onceWrapper (events.js:277:13) at Connection.emit (events.js:189:13) at Socket.<anonymous> (/home/allen/scripts/lysi/eosMain/node_modules/mongodb-core/lib/connection/connection.js:245:50) at Object.onceWrapper (events.js:277:13) at Socket.emit (events.js:189: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)

и вот мой код:

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('myDb', 'myArchiveDb', 'myUser', 'myPassword');

Я даже пытался поставить эту строкув блоке try / catch или добавлении стиля обещания .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 ]

0 голосов
/ 09 февраля 2019

Вы вызываете connect из app.js синхронно, поэтому ваши 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
})()

А затем ошибка, которую я получаю на консоли (Нет предупреждений!):

{ 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
0 голосов
/ 09 февраля 2019

Я проверил ваш код, и он отлично работает, как вы можете видеть на скриншотах ниже.Я думаю, что проблема заключается в том, что вызывает mongoConnect ()

Connecting on wrong port Successful connection

...