Помогите с ассинхронностью в телеграм боте
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 |
Ничего не понимаю в ботах, для телеги, но смущает ваш map.
Сам map должен возвращать массив. Функция, которая внутри map должна возвращать элемент массива. У вас этого ничего нет. Что такое tmp в resolve(tmp) тоже не известно. bdata это что? строка? (есть проверка bddata!='') |
Цитата:
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. |
Т.е. Хочу, чтобы поток был свободен и отвечал на start во время прохода по массиву объектов. И возвращался толко когда закончит проход.
Короче когда начимаю start она не отвечает. Ждет когда переберет весь массив, только потом дает ответ start |
Пусть код будет так:
Код:
const mysql = require("mysql2"); |
А что shellexe возвращает? Promis?
|
Цитата:
она выполняет курл и получает ответ |
Тогда надо что то вроде этого
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. Я неправильно написал? ![]() |
Часовой пояс GMT +3, время: 04:28. |