Исходник Гайд Асинхронные HTTP запросы

Тема в разделе "Lua", создана пользователем FYP, 26 фев 2018.

  1. FBenz

    FBenz Интересующийся

    Регистрация:
    12 дек 2018
    Сообщения:
    152
    Симпатии:
    10
    Переделал. Запилил вот такой код, все остальные асинхроны вырубил. Все равно крашит. Что может быть не так? Проверку не обходят, потоки в асинхронной функции успевают завершиться, проверял вручную и при помощи чата, куда выводил состояние асинхронного потока. Перед началом другого он всегда принимал значение Dead. Но все равно крашит. Может что-то не так?
    Уже подустал ломать голову над этой задачей. В лог вообще ничего не выводит. Вылетает именно игра.

    Асинхроны не встречаются, понятия не имею, что не так.
    
    
    settings.threadtwo = lua_thread.create(onGetCasefile) -- пример запуска. Где-то в onDrawFrame()
    
    function onGetCasefile()
    
    
    asyncHttpRequest('GET', "ссыль", nil, -- выполняется асинхрон
      function(response)
    --ну, тут код х
      end,
      function(err)
         sampAddChatMessage('{6600FF}Нет связи')
      end)
    
      while true do
        wait(5)
         if settings.thread:status() == 'dead' then -- ждем, когда завершится асинхронный поток (аналог settings.thread.dead)
          wait(1000)
           break -- по завершению переходим к другим асинхронам
         end
       end
    
    
      for i = 1, tonumber(casefile.get.count) do -- nick, name, old, frac, sex, status, short, invest, imgur
    
       while true do
        wait(5)
         if settings.thread:status() == 'dead' then -- проверяем, завершился ли асинхронный запрос перед тем, который в цикле
          wait(1000) -- на всякий ждем секунду
           sampAddChatMessage('{6600ff}'..tostring(settings.thread.dead))
           break
         end
       end
    
        asyncHttpRequest('GET', "ссыль2", nil,
         function(response)
          --ну, тут код х2
          end
         end,
         function(err)
          sampAddChatMessage('{6600FF}Нет связи')
         end)
    
       end
    
    
    end
    
    function asyncHttpRequest(method, url, args, resolve, reject) -- взято у ковера.
       local request_thread = effil.thread(function (method, url, args)
          local requests = require 'requests'
          local result, response = pcall(requests.request, method, url, args)
          if result then
             response.json, response.xml = nil, nil
             return true, response
          else
             return false, response
          end
       end)(method, url, args)
       if not resolve then resolve = function() end end
       if not reject then reject = function() end end
       settings.thread = lua_thread.create(function() -- Сюда я и поставил переменную, содержащую поток.
          local runner = request_thread
          while true do
             local status, err = runner:status()
             if not err then
                if status == 'completed' then
                   local result, response = runner:get()
                   if result then
                      resolve(response)
                   else
                      reject(response)
                   end
                   return
                elseif status == 'canceled' then
                   return reject(status)
                end
             else
                return reject(err)
             end
             wait(0)
          end
       end)
    end
     
  2. Frapsy

    Проверенный

    Регистрация:
    4 сен 2016
    Сообщения:
    387
    Симпатии:
    180
    Не шарю, сработает оно или нет, реализация сия костыля не моя, но держи:
    local checkvarible = -1
    function loop_async_http_request(url, args, resolve, reject)
        local request_lane = lanes.gen('*', {package = {path = package.path, cpath = package.cpath}}, function()
            local requests = require 'socket.http'
            if not requests then
                return false, result
            end
            if checkvarible ~= nil then
                local ok, result = pcall(requests.request, url, args)
                if ok then
                    return true, result
                else
                    return false, result
                end
            else
                return false
            end
        end)
        if not reject then reject = function() end end
        lua_thread.create(function()
            local lh = request_lane()
            while true do
                if not lh then
                    wait(200)
                    lh = request_lane()
                else
                    local status = lh.status
                    if status == 'done' then
                        local ok, result = lh[1], lh[2]
                        if ok then resolve(result) else reject(result) end
                        wait(500)
                        lh = request_lane()
                    elseif status == 'error' then
                        reject(lh[1])
                        wait(500)
                        lh = request_lane()
                    elseif status == 'killed' or status == 'cancelled' then
                        reject(status)
                        wait(500)
                        lh = request_lane()
                    end
                    wait(10)
                end
            end
        end)
    end
    В function(response) задавай checkvarible че нить, я не шарю зачем оно там и какой смысл несет, но оно там есть. Если не пашет - отвечаю, никто не решит, искать нужно будет по форуму разные извращения этой функции и loop_async - одно из таких.
     
    FBenz нравится это.
  3. FBenz

    FBenz Интересующийся

    Регистрация:
    12 дек 2018
    Сообщения:
    152
    Симпатии:
    10
    Короче, вроде решил проблему с вылетами асинхронов, может кому пригодится:

    Была проблема, что при использовании функции cover'a в цикле, вне зависимости от задержки и проверок, асинхроны улетали вместе с игрой в закат.
    Колупался 4 дня, чтобы найти способы это пофиксить, делал жуткие костыли и не жуткие, ничего не помогало. Решении проблемы пришло само и совершенно простое.

    Что мне помогло? Из функции асинхронного запроса cover'a я убрал создание потока, а саму функцию, содержащую асинхрон, запускал в другом потоке.
    Другими словами получилось так:
    Ваша функция с асинхронами:
    
    function getAsync() -- ваша функция, содержащая асинхроны
     for i = 1, 100 do -- сам цикл. Пробовал и While и For и Repeat. Результат одинаковый - не вылетает.
      asyncHttpRequest('GET', "ваша ссылочка", nil,
         function(response)
          -- код ответа
         end,
         function(err)
          -- код ошибки
          sampAddChatMessage('{6600FF}Нет связи')
      end)
     end
    end
    Функция запроса от cover'a:
    function asyncHttpRequest(method, url, args, resolve, reject)
       local request_thread = effil.thread(function (method, url, args)
          local requests = require 'requests'
          local result, response = pcall(requests.request, method, url, args)
          if result then
             response.json, response.xml = nil, nil
             return true, response
          else
             return false, response
          end
       end)(method, url, args)
       if not resolve then resolve = function() end end
       if not reject then reject = function() end end
        --lua_thread.create(function() -- здесь я и убрал поток
          local runner = request_thread
          while true do
             local status, err = runner:status()
             if not err then
                if status == 'completed' then
                   local result, response = runner:get()
                   if result then
                      resolve(response)
                   else
                      reject(response)
                   end
                   return
                elseif status == 'canceled' then
                   return reject(status)
                end
             else
                return reject(err)
             end
             wait(0)
          end
       --end) -- конец убранного потока
    end
    Вызов функции с асинхронами где-то внути кода:
    
    lua_thread.create(function()
     --Ваш код
      getAsync()
     -- Ваш код х2
    end)
    -- Либо
    lua_thread.create(getAsync)
    Не знаю, поможет ли кому-то еще, но лично мне помогло, проработал скрипт 10 минут +-, дальше не стал проверять, работает, данные передаются в лучшем виде, фризов не наблюдал. Запускал до 5 циклов одновременно (с разными переменными и задачами, естественно), тоже работает без искажений и вылетов.
     
    #108 FBenz, 18 май 2019 в 15:28
    Последнее редактирование: 18 май 2019 в 19:53
    DonHomka и Seceder нравится это.
  4. #Northn

    #Northn нортхн
    Проверенный

    Регистрация:
    10 авг 2017
    Сообщения:
    836
    Симпатии:
    327
    Зачем 100 раз делать запрос на сайт? Суицидник?
     
  5. AppleThe

    AppleThe print("Hello World")
    Проверенный

    Регистрация:
    18 июл 2013
    Сообщения:
    238
    Симпатии:
    242
    Наверное теста ради
     
  6. FBenz

    FBenz Интересующийся

    Регистрация:
    12 дек 2018
    Сообщения:
    152
    Симпатии:
    10
    Именно так. Делал с циклом в 100, 5 циклов одновременно, не вылетало. Больше не пробовал, ибо нафиг не нужно
     
  7. Pakulichev

    Pakulichev кошачий сквад
    Проверенный

    Регистрация:
    28 окт 2017
    Сообщения:
    619
    Симпатии:
    220
    DDoS сайтов проводит из под Lua, а потом все удивляются почему же BH отдыхает
     
    DonHomka и #Northn нравится это.