Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 29.01.2023, 12:09
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Помогите с ассинхронностью в телеграм боте
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
  {command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
  {command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'}, 
  {command: '/notif', description: 'show logs'},
  {command: '/notifoff', description: 'hide logs'},  
  {command: '/my', description: 'your nodes'}
])

 const start = () => {
    bot.on('message', async msg => {
      const text = msg.text;     
      
      //console.log(msg)
      if(text === '/start'){
        return bot.sendMessage(msg.from.id, `Welcome!`)
      }

      if(text === '/my'){
        console.log("нажат my")   
        bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)     
        return
      }
      return bot.sendMessage(msg.from.id, `Unknown command`)      
    })
  }
  start()
  var pool=mysql.createPool(mysqlConfig);
  cron.schedule('* */1 * * * *', async () => { 
    let bddata;
    pool.getConnection(function(err,connection){
      if (err) {
       connection.release();
       console.log("ошибка соед");
        //bot.sendMessage(msg.from.id,'нет соединения с БД')        
       reject(err)
      }else{
        console.log("зашли читать БД");
        const sql = `SELECT * FROM userip`;
        pool.query(sql, '',function(err, resp) {
          if(err) {
            //bot.sendMessage(msg.from.id,'не удалось добавить данные')             
            return console.log(err);
          }
          bddata =resp
          console.log("resp")
          if(bddata && bddata!=''){
                bddata.map((val)=>{
                  console.log(val)
                  console.log("curl:")
                  
                  const p = new Promise(function(resolve, reject){
                  //let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  let tmp = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  resolve(tmp)
                  })
                  p.then(data=>{
                    console.log(data)
                  })
                })
          //let curlres = proverka();
          console.log("curl res:")
          //console.log(curlres)
            111111
          }else{
            console.log(`База пуста`)
          } 
          connection.release(); // закрываем соединение с базой данных
        })
      }
    });
    console.log("bddata")
  })


Привет! Набросал скрипт для бота и не могу разобраться с асинхронностью.
start() - это функция от бота. Прием команд от пользователя через телегу. Например /my вытаскивает все заведенные ip.

И есть второй раздел с кроном. Который мониторит. Надо чтобы второй раздел с кроном работал как бы независимо от первого. В переменную bddata загружаются сотни ip адресов. Программа вытаскивает айпи и через курл проверяет доступность. 1 адрес через курл занимает 3 секунды. Если адресов много, то это будет долго.

И дело в том, что когда вызываю /my в start, то ответ приходит только после окончания проверки всех ip из базы. Как сделать, чтобы функции в start не зависели от тормоззов функции с курлом?
Т.е. нужно, чтобы при нажатии /my сразу пришел ответ не дождавшись выполнения функции в крон

Последний раз редактировалось tarabukinivan, 29.01.2023 в 15:15.
Ответить с цитированием
  #2 (permalink)  
Старый 30.01.2023, 09:32
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Сообщение от tarabukinivan Посмотреть сообщение
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
  {command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
  {command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'}, 
  {command: '/notif', description: 'show logs'},
  {command: '/notifoff', description: 'hide logs'},  
  {command: '/my', description: 'your nodes'}
])

 const start = () => {
    bot.on('message', async msg => {
      const text = msg.text;     
      
      //console.log(msg)
      if(text === '/start'){
        return bot.sendMessage(msg.from.id, `Welcome!`)
      }

      if(text === '/my'){
        console.log("нажат my")   
        bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)     
        return
      }
      return bot.sendMessage(msg.from.id, `Unknown command`)      
    })
  }
  start()
  var pool=mysql.createPool(mysqlConfig);
  cron.schedule('* */1 * * * *', async () => { 
    let bddata;
    pool.getConnection(function(err,connection){
      if (err) {
       connection.release();
       console.log("ошибка соед");
        //bot.sendMessage(msg.from.id,'нет соединения с БД')        
       reject(err)
      }else{
        console.log("зашли читать БД");
        const sql = `SELECT * FROM userip`;
        pool.query(sql, '',function(err, resp) {
          if(err) {
            //bot.sendMessage(msg.from.id,'не удалось добавить данные')             
            return console.log(err);
          }
          bddata =resp
          console.log("resp")
          if(bddata && bddata!=''){
                bddata.map((val)=>{
                  console.log(val)
                  console.log("curl:")
                  
                  const p = new Promise(function(resolve, reject){
                  //let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  let tmp = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  resolve(tmp)
                  })
                  p.then(data=>{
                    console.log(data)
                  })
                })
          //let curlres = proverka();
          console.log("curl res:")
          //console.log(curlres)
            111111
          }else{
            console.log(`База пуста`)
          } 
          connection.release(); // закрываем соединение с базой данных
        })
      }
    });
    console.log("bddata")
  })


Привет! Набросал скрипт для бота и не могу разобраться с асинхронностью.
start() - это функция от бота. Прием команд от пользователя через телегу. Например /my вытаскивает все заведенные ip.

И есть второй раздел с кроном. Который мониторит. Надо чтобы второй раздел с кроном работал как бы независимо от первого. В переменную bddata загружаются сотни ip адресов. Программа вытаскивает айпи и через курл проверяет доступность. 1 адрес через курл занимает 3 секунды. Если адресов много, то это будет долго.

И дело в том, что когда вызываю /my в start, то ответ приходит только после окончания проверки всех ip из базы. Как сделать, чтобы функции в start не зависели от тормоззов функции с курлом?
Т.е. нужно, чтобы при нажатии /my сразу пришел ответ не дождавшись выполнения функции в крон
Пробовал весь цикл обернуть промисом:
bddata =resp
          console.log("resp")
          if(bddata && bddata!=''){
            const p = new Promise(function(resolve, reject){
              console.log("начало цикла")
                bddata.map((val)=>{
                  //let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                 
                })
                console.log("конец цикла")
                resolve(tmp)
              })
              p.then(data=>{
                console.log(data)
              })
          //let curlres = proverka();
          console.log("curl res:")
          //console.log(curlres)
            111111
          }else{
            console.log(`База пуста`)
          } 
          connection.release();

и даже так:
bddata =resp
          console.log("resp")
          const p = new Promise(function(resolve, reject){
          if(bddata && bddata!=''){
            
              console.log("начало цикла")
                bddata.map((val)=>{
                  //let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                 
                })
                console.log("конец цикла")
                resolve(tmp)
              
          //let curlres = proverka();          
          //console.log(curlres)
            111111
          }else{
            console.log(`База пуста`)
          } 
        })
        p.then(data=>{
          console.log(data)
        })
          connection.release(); // закрываем соединение с базой данных
        })

Все равно ждет конец цикла, парсит все курл, только потом идет выполнять /my
Ответить с цитированием
  #3 (permalink)  
Старый 30.01.2023, 12:34
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Ничего не понимаю в ботах, для телеги, но смущает ваш map.
Сам map должен возвращать массив.
Функция, которая внутри map должна возвращать элемент массива.
У вас этого ничего нет.

Что такое tmp в resolve(tmp) тоже не известно.
bdata это что? строка? (есть проверка bddata!='')
Ответить с цитированием
  #4 (permalink)  
Старый 30.01.2023, 14:09
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Сообщение от voraa Посмотреть сообщение
Ничего не понимаю в ботах, для телеги, но смущает ваш map.
Сам map должен возвращать массив.
Функция, которая внутри map должна возвращать элемент массива.
У вас этого ничего нет.

Что такое tmp в resolve(tmp) тоже не известно.
bdata это что? строка? (есть проверка bddata!='')
bdata - массив объектов. Это я просто для теста редактировал. Пусть будет так
if(bddata && bddata!=''){
            
              console.log("начало цикла")
              
                bddata.map((val)=>{
                  let main = shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                  
                  //let res = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                 console.log(main)
                })
                
                resolve(1)
              
          //let curlres = proverka();          
          //console.log(curlres)
            111111
          }else{
            console.log(`База пуста`)
          }

Там дело не в том, что возвращает map.

Map правильно перебирает объекты val типа:
+-----+-----------+---------------------+----------+--------+
| id  | userid    | ipu                 | propuski | worked |
+-----+-----------+---------------------+----------+--------+
| 166 | 416844240 | 109.237.85.201:9000 |        4 |      1 |
| 167 | 416844240 | 109.237.85.202:9000 |        3 |      1 |
| 168 | 416844240 | 109.237.85.203:9000 |        2 |      1 |
| 169 | 416844240 | 109.237.85.204:9000 |        0 |      1 |
| 170 | 416844240 | 109.237.85.205:9000 |        0 |      1 |
| 171 | 416844240 | 109.237.85.206:9000 |        0 |      1 |
| 172 | 416844240 | 109.237.85.207:9000 |        0 |      1 |
| 173 | 416844240 | 109.237.85.207:9000 |        0 |      1 |

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

Последний раз редактировалось tarabukinivan, 30.01.2023 в 14:17.
Ответить с цитированием
  #5 (permalink)  
Старый 30.01.2023, 14:10
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Т.е. Хочу, чтобы поток был свободен и отвечал на start во время прохода по массиву объектов. И возвращался толко когда закончит проход.
Короче когда начимаю start она не отвечает. Ждет когда переберет весь массив, только потом дает ответ start

Последний раз редактировалось tarabukinivan, 30.01.2023 в 14:13.
Ответить с цитированием
  #6 (permalink)  
Старый 30.01.2023, 15:00
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Пусть код будет так:
Код:
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
  {command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
  {command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'}, 
  {command: '/notif', description: 'show logs'},
  {command: '/notifoff', description: 'hide logs'},  
  {command: '/my', description: 'your nodes'}
])

 const start = () => {
    bot.on('message', async msg => {
      const text = msg.text;     
      
      //console.log(msg)
      if(text === '/start'){
        return bot.sendMessage(msg.from.id, `Welcome!`)
      }

      if(text === '/my'){
        console.log("нажат my")   
        bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)     
        return
      }
      return bot.sendMessage(msg.from.id, `Unknown command`)      
    })
  }
  start()
  
  //var pool=mysql.createPool(mysqlConfig);
  cron.schedule('* */1 * * * *', async () => { 

    const p = new Promise(function(resolve, reject){
      let main =[]
      for(var i = 0; i < 7;i++){
        main.push(shellexe(`curl --max-time 3 --location --silent --request POST https://fullnode.testnet.sui.io:443 --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`))
      }
      resolve(main)     
    })
    p.then(data =>{
      console.log(data)
    })
    
  })
Мне нужно как-то for обернуть в промис, чтобы /my отвечал моментально. В таком виде при вызове /my в start ответ приходит не сразу. Отвечат только когда for завершится.
Ответить с цитированием
  #7 (permalink)  
Старый 30.01.2023, 17:51
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

А что shellexe возвращает? Promis?
Ответить с цитированием
  #8 (permalink)  
Старый 31.01.2023, 02:38
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Сообщение от voraa Посмотреть сообщение
А что shellexe возвращает? Promis?
Да в нем https://www.npmjs.com/package/shelljs
она выполняет курл и получает ответ
Ответить с цитированием
  #9 (permalink)  
Старый 31.01.2023, 07:25
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Тогда надо что то вроде этого

const arp = bbdata.map (val => {
    return shellexe(`.....`);
})
// Ждем когда все закончатся
Promise.all(arp).then(data => {....}) // data массив


или

const arp = bbdata.map (val => {
    return shellexe(`.....`);
})
// обрабатываем по мере исполнения
for await (data of arp) {
....
}

Последний раз редактировалось voraa, 31.01.2023 в 07:30.
Ответить с цитированием
  #10 (permalink)  
Старый 31.01.2023, 10:59
Интересующийся
Отправить личное сообщение для tarabukinivan Посмотреть профиль Найти все сообщения от tarabukinivan
 
Регистрация: 17.08.2017
Сообщений: 19

Сообщение от voraa Посмотреть сообщение
Тогда надо что то вроде этого

const arp = bbdata.map (val => {
    return shellexe(`.....`);
})
// Ждем когда все закончатся
Promise.all(arp).then(data => {....}) // data массив


или

const arp = bbdata.map (val => {
    return shellexe(`.....`);
})
// обрабатываем по мере исполнения
for await (data of arp) {
....
}
Извините не очень понял как применить ваш код, но вроде так?:
if(bddata && bddata!=''){
              const arp = bddata.map (val => {
                  return shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
                })
              async function getData() {
                for await (data of arp) {
                  console.log(data)
                }
              }
              getData() 
              }else{
                console.log(`База пуста`)
              }

В таком ввиде все равно /my выполняется только после полного прохода по map. Я неправильно написал?
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Телеграм бот отправка сообщений со скрипта. drozd2016 Общие вопросы Javascript 0 11.02.2021 18:30
Помогите решить проблему Ingiborn Общие вопросы Javascript 0 10.07.2014 13:12
Помогите! Многоуровневые вкладки! sergeeeeee Элементы интерфейса 2 02.08.2010 23:50
помогите задать переменную в js bsgroupua Общие вопросы Javascript 3 01.02.2010 18:28