Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Инициализация асинхронног омодуля async/await (https://javascript.ru/forum/node-js-io-js/79312-inicializaciya-asinkhronnog-omodulya-async-await.html)

sniffysko 22.01.2020 15:12

Инициализация асинхронног омодуля async/await
 
Здравствуйте. Есть необходимость написать модуль, который работает с БД MS SQL, и, как вы понимаете, инициализируется асинхронно. Кроме того, этот модуль подтягивает настройки приложения из БД. Есть нечто такое:

Модуль
// SQL может генерировать более 1 ошибки. Для их чтения смотрим err.precedingErrors
const sql = require('mssql');
const config = require('./config');

const qPreference = `SELECT [code], [value] FROM [setting] WHERE [type] != 'section' FOR JSON AUTO`

class AppSql{

	constructor(){
		this.sqlConfig = {
            ...
        };
		this._pool = null;
	}

	async init(){
		try {
			this._pool = await new sql.ConnectionPool(this.sqlConfig).connect();
			const request = this._pool.request();
			const result = await request.query(qPreference);
			let resJSON = result.recordset[0];
			if(!resJSON) resJSON = [];
			config.loadData(resJSON);
		} catch (err) {
			console.log( 'AppSql.constructor error.');
		}
	}
}

// Экспорт инстанса
module.exports = new AppSql();


Вызов модуля в приложении:
const express = require('express');
const config = require('./class/config');
const app = express();


const sql = require('./class/appsql');
await sql.init();

// Тестовый обработчик запросов
app.get('/', async (req, res, next) => {
	res.status(200).send('api run');
});

const port = process.env.PORT || config.getKey('apiPort');
app.listen(port, (err, req, res) => {
	LOG.logInfo( "Application started at port: " + port );
});


Во время запуска выдает ошибку:
await sql.init();
^^^^^
SyntaxError: await is only valid in async function
...
[nodemon] app crashed - waiting for file changes before starting...

В чем ошибка и как сделать правильно?

Aetae 22.01.2020 16:21

Цитата:

В чем ошибка.
SyntaxError: await is only valid in async function
Цитата:

Как сделать правильно?
Завернуть всё в async функцию вызываемую сразу после создания.

Или использовать await-top/аналоги.

Или поставить последние версии ноды и запускать с флагом --harmony-top-level-await.

sniffysko 22.01.2020 17:44

Текст ошибки я понял. :о)

Не понятно что сделал неправильно.
Конструктор у класса AppSql -- синхронный.
Асинхронный код находится в функции Init (строка 16 первого блока кода)
Вызв функции осуществляется с await: await sql.init();

Вроде бы так как вы говорите. Можете подкорректировать код как правильно? Не понимаю что именно не так.

Aetae 22.01.2020 23:11

>SyntaxError: await действителен только в асинхронной функции
>в асинхронной функции


Где у вас await?

sniffysko 04.02.2020 01:13

Спасибо за подсказку. Node.js для меня внове и потому логика приложений до меня туговато доходит. :)
Сделал так как вы советовали и без привлечения внешних ресурсов.
Конструктор сделал синхронным, асинхронная инициалазация вынесена в асинхронные же функции. Инициализацию выполнил в самовызывающейся анонимной функции:

Модуль SQL
async init(){
    try {
        this._pool = await new sql.ConnectionPool(this.sqlConfig).connect();
        this._pool.on('error', (err) => {
            LOG.logError( MSG.fgetMsg('eSqlCommon', err.stack) );
        })
        LOG.logInfo( MSG.getMsg('iSqlConnected') );
    } catch (err) {
        LOG.logError( 'AppSql.constructor. \n' + MSG.fgetMsg('eSqlConnect', err.stack) );
    }
}

async loadPreferences(){
    try {
        const request = this._pool.request();
        const result = await request.query(qPreference);
        let resJSON = result.recordset[0];
        if(!resJSON) resJSON = [];
        config.loadData(resJSON);
        LOG.logDebug( "AppSql.loadPreferences\n" + MSG.fgetMsg('mConfigRead', qPreference, resJSON.length, config.toString()) );
    } catch (error) {
        LOG.logError( "AppSql.loadPreferences\n" +  MSG.fgetMsg('mConfigRead', error) ); 
    }
}


главный модуль приложения:
const express = require('express');
const sanitizer = require('express-sanitizer');
const config = require('./class/config');
const app = express();

const LOG = require('./class/logger');
const sql = require('./class/appsql');
const apputil = require('./class/apputil');
const RouteRegistrator = require('./class/routeregistrator');

app.use(express.json());

// Корневой обработчик запросов. Для красоты
app.get('/', async (req, res, next) => {
	res.status(200).send('api run');
	next();
});


// Асинхронная инициализация приложения
(async () => {
	// Инициализируем SQL и читаем настройки приложения
	await sql.init();
	await sql.loadPreferences();
	// Регистрируем роуты
	const reg = new RouteRegistrator(app);
	reg.register();

	// Глобальный обработчик ошибок.
	apputil.initGlobalErrorHandler(app, LOG);

	// Запускаем сервер
	const port = process.env.PORT || config.getKey('apiPort');
	app.listen(port, (err, req, res) => {
		LOG.logInfo( "Application started at port: " + port );
	});
})();


Часовой пояс GMT +3, время: 09:53.