Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   promise (async await) (https://javascript.ru/forum/node-js-io-js/82531-promise-async-await.html)

fxobject 20.05.2021 13:15

promise (async await)
 
Уважаемые господа!
Необходимо осуществить чтение из БД и при этом нужно дождаться результата.
есть класс MSSQL и у него функция
async readQuery( option ){
.......
здесь
формируем и выполняем запрос
ждем его выполнения
return result; //--- результат запроса (массив объектов)
}
все замечательно. при выполнении функции все происходит как нужно
но дело в том, что async сам по себе промис, и выполняется отдельно.
т.е. в том месте где нужно обратится к функции:
let query = { query:'select * from dbo.spin' }
let result = global.mssql.readQuery(query); //--- а вот тут не ждем
//--- а сюда ходить без результата нельзя
ну и соответственно result получается не тот, который должна вернуть функция, а объект промиса.
Собственно вопрос - как дождаться выполнения этой функции?
Спасибо

fxobject 20.05.2021 13:18

т.е. получается ли так, что в том месте где я вызываю эту функцию и мне необходимо дожидаться результата я должен объявить async (функция откуда делается вызов) и применять await ?

ksa 20.05.2021 14:40

fxobject, можно сделать свою async-функцию и потом в ней все вызывать как await-функции...

ksa 20.05.2021 14:42

fxobject, вот примерчик такого
https://habr.com/ru/post/334772/

fxobject 20.05.2021 16:56

Увы вопрос не понят. Сейчас он уже даже не в технической а в концептуальной форме.
функция А(){
ФункцияКоторуюНужноПодожд ать(); //" асинхронная "
//--- здесь функция которую нужно подождать точно завершена
следующий код
}

Функцию А точно нельзя делать async
Вот вопрос ставится именно так. Все остальные комбинации (технический) как реализовать, async и всякое такое не вариант.
На вопрос - как? Ответ скорей всего никак.
можно организовать некую переменную для контроля завершения. например так:
let finished = false;
ФункцияКоторуюНужноПодожд ать();
while( finished ){}
Но так тоже не пойдет - JS это не многопоточная среда. Чтобы выполнился "асинхронный" (на самом деле он ни какой не асинхронный) код необходимо закончить цикл и уйти в ядро JS. Потому как пока крутится цикл - все так называемые асинхронные задачи остановлены.
Если есть вариант в цикле отдать управление очереди JS и потом получить обратно в то же самое место, то задачу решить в такой постановке удастся.
Например
let finished = false;
ФункцияКоторуюНужноПодожд ать();
while( finished ){
ОтдатьУправлениеОчередиJS() ;
}

fxobject 20.05.2021 17:02

Цитата:

Сообщение от ksa (Сообщение 536889)
fxobject, можно сделать свою async-функцию и потом в ней все вызывать как await-функции...

Свою async-функцию сделать неможна. Потому что, как только делается такая функция сразу подразумевается что есть вышестоящий код, который будет ее ожидать.
Но такого кода нет.
Т.е. вот примерно так
А(){
B();
//--- вот тут что будет? подразумевается что с завершена!
}
B(){
c() - и вот тут типа своя функция которая ждет. А что будет с кодом
выше? В функции А?
}

voraa 20.05.2021 17:58

Цитата:

Сообщение от fxobject
Функцию А точно нельзя делать async

Любую функцию можно объявить async
Цитата:

Сообщение от fxobject
Свою async-функцию сделать неможна. Потому что, как только делается такая функция сразу подразумевается что есть вышестоящий код, который будет ее ожидать.
Но такого кода нет.

Как нет кода? А кто же ее вызывает?
Если не надо ждать окончания асинхронной функции, значит не надо вызывать ее с await. Просто вызвать и все, а как она сработает, так и сработает.

voraa 20.05.2021 18:03

Цитата:

Сообщение от fxobject
let query = { query:'select * from dbo.spin' }
let result = global.mssql.readQuery(query); //--- а вот тут не ждем
//--- а сюда ходить без результата нельзя
ну и соответственно result получается не тот, который должна вернуть функция, а объект промиса.
Собственно вопрос - как дождаться выполнения этой функции?

Выже сами писали
Цитата:

Сообщение от fxobject
есть класс MSSQL и у него функция
async readQuery( option ){

Значит вызывать ее надо
let result = await global.mssql.readQuery(query);

fxobject 20.05.2021 18:40

так. постараюсь еще раз объяснить свою позицию.
function А(){
//--- где то там вызовется асинхинхронная функция
B();
//Точка 1 вот тут нужны результаты асинхронной функции
}
B(){
что то делаем
//--- где то там вызовется асинхинхронная функция
С();
// Точка 2 а тут тем более нужны результаты асинхронной функции
}

C(){
//-- еще раз что то делаем
D() АСИНХРОННО!!!
// Точка 3
// надо дождаться D ниже код зависит от результата
// не только ниже но и по стеку вызовов функции все остальные тоже
// зависят и любой ваш async запланируем выполнение D (ского бы вы
не ставили await ов), но сразу же D завершится с возвратом промиса
и пойдет по коду дальше..... выйдет из всех процедур (а тама ждут результата) и только вывалившись в ядро JS (попав в очередь задач) начнет выполнять D. завершит D передаст результаты then и что потом?
А мне они нужны в точке Точка 1,2,3
}

Господа, я понимаю что такое await и все что с этим связано - вникните в постановку задачи. Если идти по вашему предложению, тогда всю логику (Точка 1,2,3) необходимо запихивать в колбэк (это собственно и есть ваш промис) для асинхронной функции.
Это понятно, даже правильно. В таких случаях кроме promise есть и другие интересные механизмы....
вопрос встал чисто теоретически - ну вот захотелось. можно или нет?

ksa 20.05.2021 18:54

Цитата:

Сообщение от fxobject
На вопрос - как? Ответ скорей всего никак.

Скорее ты не совсем понимаешь всех возможностей Ноды... :(

Есть еще события. Их можно назначить при вызове асинхронной функции, а инициировать событие уже в колбеке, когда данные получены и их можно передать в обработчик события...

ksa 20.05.2021 18:55

Цитата:

Сообщение от fxobject
постараюсь еще раз объяснить свою позицию

Пока у тебя ну никак не получаются тестовые примеры. :(

Если бы ты смог сделать нормальный тестовый пример - на нем можно было бы показать варианты решений.

ksa 20.05.2021 18:56

Цитата:

Сообщение от fxobject
Если идти по вашему предложению, тогда всю логику (Точка 1,2,3) необходимо запихивать в колбэк

Может это ты не понимаешь про что мы тебе пишем? :D

ksa 20.05.2021 19:00

Цитата:

Сообщение от fxobject
вопрос встал чисто теоретически - ну вот захотелось. можно или нет?

Ты напомнил мне старый анекдот...

К врачу (В) приходит пациент (П)...
В - На что жалуетесь?
П - Понимаете... Когда я делаю вот так (скручивается в неимоверную позу) - у меня начинает болеть вот тут!
В - Не делайте так...

fxobject 20.05.2021 19:16

Цитата:

Сообщение от ksa (Сообщение 536899)
Пока у тебя ну никак не получаются тестовые примеры. :(

Если бы ты смог сделать нормальный тестовый пример - на нем можно было бы показать варианты решений.

Пример:
global.X = '';
function A(){
с();
let z = global.X; //-- вот тут должно быть значение 'новая строка'
}
function B(){
d(); //--- инициализирует global.X
let z = global.X; //-- вот тут должно быть значение 'новая строка'
}
async d(){
global.X = 'новая строка' ;
}

без вопросов - "а зачем"? расставляйте что надо сделать (только не поднимайте async до самого верха до функции A)

ksa 20.05.2021 19:27

Цитата:

Сообщение от fxobject
function А(){
   //--- где то там вызовется асинхинхронная функция
   B();
   //Точка 1 вот тут нужны результаты асинхронной функции
}

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

function А(){
   const res = myFnc()
   B();
   //Точка 1 вот тут будешь использовать результаты асинхронной функции
}
async myFnc() {
   const res = await <та_самая_асанхронная_функция>
   return res
}

fxobject 20.05.2021 19:29

я привел пример. расставьте там

fxobject 20.05.2021 19:30

нужен же был нормальный тестовый пример?
поставьте на нем

ksa 20.05.2021 19:36

Цитата:

Сообщение от fxobject
я привел пример. расставьте там

1. Для нормального вида примера начинай учиться форматировать код
2. Там у тебя непонятка с функцией c()

ksa 20.05.2021 19:41

Цитата:

Сообщение от fxobject
global.X = '';
function A(){
с();
let z = global.X; //-- вот тут должно быть значение 'новая строка'
}

Если вызывать A() - откуда брать c() ?
Каким боком тут B() ?

fxobject 20.05.2021 19:44

с()
рассматривать как B()

ksa 20.05.2021 19:49

fxobject, вот, взял с твоего "текста" понятный кусок...
Цитата:

Сообщение от fxobject
function B(){
d(); //--- инициализирует global.X
let z = global.X; //-- вот тут должно быть значение 'новая строка'
}
async d(){
global.X = 'новая строка' ;
}

На его примере показываю нормальный тестовый пример. ;)

let X

B()

function B() {
	myFnc()
	alert(X)
}
async function myFnc() {
	return await d()
}
async function d() {
	X = 'новая строка' 
}

ksa 20.05.2021 19:53

Цитата:

Сообщение от fxobject
с()
рассматривать как B()

Как вариант...

let X
A()

function A(){
	B();
	alert('Это из A ' + X)
}
function B() {
	myFnc()
	alert('Это из B ' + X)
}
async function myFnc() {
	return await d()
}
async function d() {
	X = 'новая строка' 
}

ksa 20.05.2021 20:17

Цитата:

Сообщение от fxobject
с()
рассматривать как B()

Твой "пример" и так работает...

let X
A()
function A(){
	B();
	alert('Из A ' + X)
}
function B(){
	d();
	alert('Из B ' + X)
}
async function d(){
	X = 'новая строка' ;
}

ksa 20.05.2021 20:28

Цитата:

Сообщение от fxobject
расставляйте что надо сделать (только не поднимайте async до самого верха до функции A)

Т.е. так тоже можно?

let X
A()

function A(){
	B().then(res => alert('Из A ' + X))
}
async function B(){
	d().then(res => alert('Из B ' + X));
}
async function d(){
	X = 'новая строка' ;
}

voraa 20.05.2021 20:43

Цитата:

Сообщение от fxobject
только не поднимайте async до самого верха до функции A

А почему собственно?

voraa 20.05.2021 20:46

Цитата:

Сообщение от fxobject
выйдет из всех процедур (а тама ждут результата) и только вывалившись в ядро JS (попав в очередь задач) начнет выполнять D

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

ksa 20.05.2021 20:47

Цитата:

Сообщение от voraa
А почему собственно?

Он просил про это не спрашивать... :nono:

Цитата:

Сообщение от fxobject
без вопросов - "а зачем"?


voraa 20.05.2021 21:04

Ну я понимаю, что бывают ситуации, когда очень нужно вызвать асинхронную функцию, дождаться результата и обработать его с верхнего уровня, где нельзя использовать await (вроде в последних Chrome и Node уже можно). Но ведь тогда так можно

;(async function ()  {
   let res = await asfunc ();
  // обрабатываем результат
})();

ksa 20.05.2021 21:33

Цитата:

Сообщение от voraa
Но ведь тогда так можно

Раздел ведь про Node.JS - тогда там почти все наследовано от eventEmitter, значит можно использовать события.

const o = asfunc().then(res => o.emit('data', res))
o.on('data', (err, res) => alert(res))

fxobject 20.05.2021 22:59

подписку на события использую постоянно. вопрос технический. пытаюсь упорядочить представление о предмете.
Итак предложенный работающий вариант:
let X
A()
function A(){
B();
alert('Это из A ' + X)
}
function B() {
myFnc()
alert('Это из B ' + X)
}
async function myFnc() {
return await d()
}
async function d() {
X = 'новая строка'}
Действительно выдает правильный результат. Что внесло еще больше смятений..... потому как не должен.
Внесем в него небольшие поправки....
давайте задержим выполнение функции MyFunc
например так:
async function myFnc() {
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>resolve("ok"),4000)});
let result = await promise;
alert(result);
return await d()
}
Вот так уже не работает......

fxobject 20.05.2021 23:02

задержку можно также перенести в функцию D. Она же асинхронная.... просто задержать ее. и все перестает работать

fxobject 20.05.2021 23:04

т.е. получается что если промис делает resolve или reject сразу. То мы получаем завершенный промис тоже сразу... и тогда приведенный пример действительно работает. Хотя не должен!

ksa 20.05.2021 23:08

Цитата:

Сообщение от fxobject
Вот так уже не работает......

Мои функции "ломать" не нужно. :D

Я там тебе много вариантов выкладывал, а ты так и не научился делать нормальные примеры. :(

ksa 20.05.2021 23:09

Цитата:

Сообщение от fxobject
Хотя не должен!

Всегда удивляли такие высказывания. :D

fxobject 20.05.2021 23:10

Цитата:

Сообщение от ksa (Сообщение 536933)
Мои функции "ломать" не нужно. :D

Я там тебе много вариантов выкладывал, а ты так и не научился делать нормальные примеры. :(

А хамить не нужно. Мы С вами пивасик вместе не квасили. Что это за фамильярность такая?

ksa 20.05.2021 23:11

Цитата:

Сообщение от fxobject
Что это за фамильярность такая?

Это свободный форум если че...
И я тебе ничем не обязан.

fxobject 20.05.2021 23:12

Понятно ))) А вчера кошек душили....... душили, душили .....)))))))


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