Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.01.2020, 15:12
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Инициализация асинхронног омодуля 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...

В чем ошибка и как сделать правильно?
Ответить с цитированием
  #2 (permalink)  
Старый 22.01.2020, 16:21
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,480

Цитата:
В чем ошибка.
SyntaxError: await is only valid in async function
Цитата:
Как сделать правильно?
Завернуть всё в async функцию вызываемую сразу после создания.

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

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

Последний раз редактировалось Aetae, 22.01.2020 в 16:55.
Ответить с цитированием
  #3 (permalink)  
Старый 22.01.2020, 17:44
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

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

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

Вроде бы так как вы говорите. Можете подкорректировать код как правильно? Не понимаю что именно не так.
Ответить с цитированием
  #4 (permalink)  
Старый 22.01.2020, 23:11
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,480

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


Где у вас await?
__________________
29375, 35
Ответить с цитированием
  #5 (permalink)  
Старый 04.02.2020, 01:13
Аспирант
Отправить личное сообщение для sniffysko Посмотреть профиль Найти все сообщения от sniffysko
 
Регистрация: 20.10.2009
Сообщений: 79

Спасибо за подсказку. 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 );
	});
})();
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск