Zwrot callback serwera nil: callbacks ESX, QBCore i ox_lib
ESX.TriggerServerCallback, QBCore TriggerCallback i lib.callback.await zwracają nil? Jak każdy callback działa na serwerze i kliencie, i powody, dla których zwracają nic.
Skrypt klienta pyta serwer o dane, a co wraca to nil, lub nic w ogóle:
SCRIPT ERROR: @my_script/client/main.lua:21: attempt to index a nil value (local 'result')Callbacki serwera to sposób, w jaki klient pyta serwer pytanie i otrzymuje odpowiedź. Każdy framework ma swój, a ox_lib ma jeden, który działa wszędzie. Ten artykuł pokazuje trzy i dlaczego zwracają nil.
ESX
Zarejestruj na serwerze, wyzwól z klienta:
-- 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)Funkcja serwera otrzymuje source i cb, i przechodzisz odpowiedź do cb. Dodatkowe argumenty z klienta przybyją po cb. Funkcja klienta otrzymuje to co cb wysłał.
QBCore
Nazwy się różnią, kształt jest taki sam:
-- 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)Jeśli ESX lub QBCore to nil wewnątrz skryptu, callback nigdy się nie rejestruje. Zobacz ESX is nil i QBCore is nil.
ox_lib
Callbacki ox_lib nie potrzebują frameworku, a odpowiedź to wartość zwrotu zamiast funkcji 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)Drugi argument await to opóźnienie w milisekundach między wezwaniem a odpowiedzią (użyj false dla żadnego). Argumenty dla serwera go następują:
local ok = lib.callback.await('my_script:buy', false, 'burger', 2)lib.callback.register('my_script:buy', function(source, item, amount)
-- ...
return true
end)Aby callback istniał, skrypt ładuje ox_lib w swoim manifeście:
shared_script '@ox_lib/init.lua'Bez niego, lib to nil: zobacz ox_lib init.lua not found.
Serwer może również wezwać klienta: lib.callback.await('name', playerId, ...) na serwerze, z lib.callback.register na kliencie. Jeśli wolisz brak czekania, lib.callback('name', false, function(result) end) przyjmuje funkcję zamiast.
Dlaczego callback zwraca nil
Prawie każdy przypadek to jeden z nich:
- Nazwa się nie zgadza. Nazwy rejestracji i wyzwolenia muszą być identyczne, łącznie z wielkością liter. Literówka nie podnosi błędu, który zauważysz, po prostu nigdy nie odpowiada.
- To nie jest zarejestrowane. Plik serwera nigdy nie działał: brakuje go z
server_scripts, zasób nie uruchomił się, lub nie powiódł się przed osiągnięciem linii rejestracji. - Błąd na serwerze, przed odpowiedzią. Jeśli funkcja serwera się nie powiedzie, na przykład
xPlayerto nil, odpowiedź nigdy nie jest wysłana. Sprawdzaj konsolę serwera, nie klienta. - Nigdy nie wezwiesz
cbna każdej ścieżce. Na ESX i QBCore, gałąź, która zwraca bez wezwaniacb(...)pozostawia klienta czekającego:
-- 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)- Zapomnisz
returnna ox_lib. Funkcjalib.callback.register, która nie mareturnodpowiadanil. - Wezwiesz za wcześnie. Callback klienta odpalony przy starcie skryptu może osiągnąć serwer, zanim jego rejestracja działała, po restarcie na przykład. Wyzwól go, gdy gracz się załaduje.
- Mieszane style. Callback zarejestrowany z
lib.callback.registernie może być wezwany zESX.TriggerServerCallback. Użyj pasującej pary.
Wskazówka: aby dowiedzieć się, który przypadek masz, dodaj
Ochronę przed nil na kliencie
Traktuj odpowiedź jako coś, co może brakować:
local money = lib.callback.await('my_script:getMoney', false)
if not money then
return print('No answer from the server')
endDla starszych frameworków, sprawdzaj argument przed jego indeksowaniem:
QBCore.Functions.TriggerCallback('my_script:getJob', function(job)
if not job then return end
print(job)
end)Który się используется
- Pisanie dla jednego frameworku tylko: jego własny callback jest w porządku.
- Pisanie dla kilka frameworków, lub dla QBox: użyj ox_lib, więc jeden callback działa wszędzie.
- Pisanie nowego kodu:
lib.callbackzwraca wartości i czyta się jak zwykła funkcja, co sprawia, że błędy są łatwiejsze do zauważenia.
Jeśli przenosisz skrypt między ESX i QBCore, nazwy callback to jeden wiersz w mapie funkcji.
Lista kontrolna
| Symptom | Naprawa |
|---|---|
| Wynik to nil | Sprawdzaj, czy nazwa dokładnie się zgadza po obu stronach |
| Nigdy nie odpowiada | Upewnij się, że plik serwera jest w manifeście i zasób uruchomił się |
| Błąd w konsoli serwera | Napraw to; niepowodzenie callback nie wysyła odpowiedzi |
| ESX lub QBCore: brak odpowiedzi na niektórych ścieżkach | Wezwij cb(...) na każdej gałęzi |
| ox_lib: wynik nil | Dodaj return do funkcji lib.callback.register |
lib to nil |
Dodaj shared_script '@ox_lib/init.lua' do manifestu |
Szybkie odpowiedzi
Jaka jest różnica między callbackiem a zdarzeniem?
Zdarzenie wysyła wiadomość i nie czeka na odpowiedź. Callback pyta drugą stronę i otrzymuje wartość z powrotem, więc klient może używać dane, które zna tylko serwer.
Czy mogę używać ox_lib callbacks na ESX lub QBCore?
Tak. ox_lib jest niezależny od frameworku, więc lib.callback działa na ESX, QBCore i QBox, o ile ox_lib jest uruchomiony i załadowany przez skrypt.
Dlaczego lib.callback.await zatrzymuje mój skrypt na chwilę?
Czeka na odpowiedź serwera, więc podda wątek. Jeśli serwer nigdy nie odpowiada, ponieważ callback brakuje lub błędy, wątek ciągle czeka lub nie działa z błędem.


