Callback сервера возвращает nil: ESX, QBCore и ox_lib callbacks
ESX.TriggerServerCallback, QBCore TriggerCallback и lib.callback.await возвращают nil? Как каждый callback работает на сервере и клиенте и причины, почему они ничего не возвращают.
Скрипт клиента просит сервер о данных, и то, что приходит обратно, — это nil или ничего вообще:
SCRIPT ERROR: @my_script/client/main.lua:21: attempt to index a nil value (local 'result')Server callbacks — это как клиент просит сервер вопрос и получает ответ. Каждый фреймворк имеет свой, и ox_lib имеет один, который работает везде. Эта статья показывает три и почему они возвращают nil.
ESX
Зарегистрируйте на сервере, инициируйте с клиента:
-- server
ESX.RegisterServerCallback('my_script:getMoney', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
cb(xPlayer.getMoney())
end)-- client
ESX.TriggerServerCallback('my_script:getMoney', function(money)
print(money)
end)Функция сервера получает source и cb, и вы передаете ответ к cb. Дополнительные аргументы от клиента прибывают после cb. Функция клиента получает то, что cb отправил.
QBCore
Имена отличаются, форма одинакова:
-- server
local QBCore = exports['qb-core']:GetCoreObject()
QBCore.Functions.CreateCallback('my_script:getMoney', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
cb(Player.PlayerData.money.cash)
end)-- client
local QBCore = exports['qb-core']:GetCoreObject()
QBCore.Functions.TriggerCallback('my_script:getMoney', function(money)
print(money)
end)Если ESX или QBCore равен nil внутри скрипта, callback никогда не регистрируется. Смотрите ESX is nil и QBCore is nil.
ox_lib
ox_lib callbacks не нуждаются в фреймворке, и ответ — это возвращаемое значение вместо функции cb:
-- server
lib.callback.register('my_script:getMoney', function(source)
local xPlayer = ESX.GetPlayerFromId(source)
return xPlayer.getMoney()
end)-- client
local money = lib.callback.await('my_script:getMoney', false)
print(money)Второй аргумент await — это задержка в миллисекундах между вызовом и ответом (используйте false для отсутствия). Аргументы для сервера следуют:
local ok = lib.callback.await('my_script:buy', false, 'burger', 2)lib.callback.register('my_script:buy', function(source, item, amount)
-- ...
return true
end)Для того чтобы callback существовал, скрипт загружает ox_lib в его манифесте:
shared_script '@ox_lib/init.lua'Без него lib равен nil: смотрите ox_lib init.lua not found.
Сервер также может вызвать клиента: lib.callback.await('name', playerId, ...) на сервере, с lib.callback.register на клиенте. Если вы предпочитаете не ждать, lib.callback('name', false, function(result) end) принимает функцию вместо.
Почему callback возвращает nil
Почти каждый случай — это один из этих:
- Имя не совпадает. Имена регистрации и инициирования должны быть идентичными, включая случай. Опечатка не вызывает ошибку, которую вы заметите, это просто никогда не отвечает.
- Это не зарегистрировано. Файл сервера никогда не работал: это отсутствует в
server_scripts, ресурс не запустился или он не выполнился перед достижением строки регистрации. - Ошибка на сервере, перед ответом. Если функция сервера ошибается, например
xPlayerравен nil, ответ никогда не отправляется. Проверьте консоль сервера, а не консоль клиента. - Вы никогда не вызываете
cbна каждом пути. На ESX и QBCore, ветвь, которая возвращает без вызоваcb(...)оставляет клиента в ожидании:
-- wrong: no cb when the player is missing
ESX.RegisterServerCallback('my_script:getJob', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer then
cb(xPlayer.job.name)
end
end)-- right
ESX.RegisterServerCallback('my_script:getJob', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
cb(xPlayer and xPlayer.job.name or nil)
end)- Вы забыли
returnна ox_lib. Функцияlib.callback.register, которая не имеетreturn, отвечаетnil. - Вы вызываете слишком рано. Callback клиента, инициированный при запуске скрипта, может достичь сервера перед его регистрацией, после перезагрузки, например. Инициируйте после загрузки игрока.
- Смешанные стили. Callback, зарегистрированный с
lib.callback.register, не может быть вызван сESX.TriggerServerCallback. Используйте совпадающую пару.
Совет: чтобы узнать, какой случай у вас, добавьте
Защищайтесь от nil на клиенте
Обрабатывайте ответ как что-то, что может быть отсутствующим:
local money = lib.callback.await('my_script:getMoney', false)
if not money then
return print('No answer from the server')
endДля более старых фреймворков проверьте аргумент перед его индексированием:
QBCore.Functions.TriggerCallback('my_script:getJob', function(job)
if not job then return end
print(job)
end)Какой использовать
- Написание для одного фреймворка только: его собственный callback хорош.
- Написание для нескольких фреймворков или для QBox: используйте ox_lib, поэтому один callback работает везде.
- Написание нового кода:
lib.callbackвозвращает значения и читает как нормальная функция, что делает ошибки легче заметить.
Если вы переносите скрипт между ESX и QBCore, имена callback — это одна строка в функции карты.
Контрольный список
| Симптом | Исправление |
|---|---|
| Результат равен nil | Проверьте, что имя точно совпадает на обеих сторонах |
| Никогда не отвечает | Убедитесь, что файл сервера находится в манифесте и ресурс запущен |
| Ошибка в консоли сервера | Исправьте; неудачный callback не отправляет ответ |
| ESX или QBCore: нет ответа на некоторых путях | Вызовите cb(...) на каждой ветви |
| ox_lib: nil результат | Добавьте return в функцию lib.callback.register |
lib равен nil |
Добавьте shared_script '@ox_lib/init.lua' в манифест |
Короткие ответы
В чем разница между callback и событием?
Событие отправляет сообщение и не ждет ответа. Callback просит другую сторону и получает значение обратно, поэтому клиент может использовать данные, которые только сервер знает.
Могу ли я использовать ox_lib callbacks на ESX или QBCore?
Да. ox_lib независим от фреймворка, поэтому lib.callback работает на ESX, QBCore и QBox пока ox_lib запущен и загружен скриптом.
Почему lib.callback.await останавливает мой скрипт на время?
Он ждет ответа сервера, поэтому он выдерживает поток. Если сервер никогда не отвечает, потому что callback отсутствует или ошибки, поток продолжает ждать или не выполняется с ошибкой.


