El callback del servidor devuelve nil: callbacks de ESX, QBCore y ox_lib
¿ESX.TriggerServerCallback, QBCore TriggerCallback y lib.callback.await devuelven nil? Cómo funciona cada callback en el servidor y cliente, y las razones por las que no devuelven nada.
Un script de cliente pregunta al servidor por datos, y lo que regresa es nil, o nada en absoluto:
SCRIPT ERROR: @my_script/client/main.lua:21: attempt to index a nil value (local 'result')Los callbacks del servidor son cómo el cliente pregunta al servidor una pregunta y obtiene una respuesta. Cada framework tiene el suyo propio, y ox_lib tiene uno que funciona en todas partes. Este artículo muestra los tres y por qué devuelven nil.
ESX
Registra en el servidor, activa desde el cliente:
-- 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)La función del servidor obtiene source y cb, y pasas la respuesta a cb. Los argumentos extra del cliente llegan después de cb. La función del cliente recibe lo que cb envió.
QBCore
Los nombres difieren, la forma es la misma:
-- 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)Si ESX o QBCore es nil dentro del script, el callback nunca se registra. Consulta ESX es nil y QBCore es nil.
ox_lib
Los callbacks de ox_lib no necesitan un framework, y la respuesta es un valor de retorno en lugar de una función 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)El segundo argumento de await es un retraso en milisegundos entre la llamada y la respuesta (usa false para ninguno). Los argumentos para el servidor lo siguen:
local ok = lib.callback.await('my_script:buy', false, 'burger', 2)lib.callback.register('my_script:buy', function(source, item, amount)
-- ...
return true
end)Para que el callback exista, el script carga ox_lib en su manifiesto:
shared_script '@ox_lib/init.lua'Sin él, lib es nil: consulta ox_lib init.lua no encontrado.
El servidor también puede llamar a un cliente: lib.callback.await('name', playerId, ...) en el servidor, con lib.callback.register en el cliente. Si prefieres no esperar, lib.callback('name', false, function(result) end) toma una función en su lugar.
Por qué un callback devuelve nil
Casi todos los casos son uno de estos:
- El nombre no coincide. Los nombres de registro y disparo deben ser idénticos, incluyendo mayúsculas/minúsculas. Un typo no genera un error que notarás, simplemente nunca responde.
- No está registrado. El archivo del servidor nunca se ejecutó: falta de
server_scripts, el recurso no se inició, o falló antes de alcanzar la línea de registro. - Un error en el servidor, antes de la respuesta. Si la función del servidor da error, por ejemplo
xPlayeres nil, la respuesta nunca se envía. Comprueba la consola del servidor, no la del cliente. - Nunca llamas a
cben cada ruta. En ESX y QBCore, una rama que regresa sin llamar acb(...)deja al cliente esperando:
-- 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)- Olvidaste
returnen ox_lib. Una funciónlib.callback.registerque no tienereturnrespondenil. - Lo llamaste demasiado pronto. Un callback de cliente disparado al inicio del script puede llegar al servidor antes de que se ejecute su registro, después de un reinicio por ejemplo. Actívalo después de que el jugador haya cargado.
- Estilos mezclados. Un callback registrado con
lib.callback.registerno puede ser llamado conESX.TriggerServerCallback. Usa el par correspondiente.
Consejo: para saber cuál caso tienes, añade un
Protégete contra nil en el cliente
Trata la respuesta como algo que puede estar faltando:
local money = lib.callback.await('my_script:getMoney', false)
if not money then
return print('No answer from the server')
endPara los frameworks más antiguos, comprueba el argumento antes de indexarlo:
QBCore.Functions.TriggerCallback('my_script:getJob', function(job)
if not job then return end
print(job)
end)Cuál usar
- Escribir solo para un framework: su propio callback está bien.
- Escribir para varios frameworks, o para QBox: usa ox_lib, así que un callback funciona en todas partes.
- Escribir código nuevo:
lib.callbackdevuelve valores y se lee como una función normal, lo que hace que los errores sean más fáciles de detectar.
Si portas un script entre ESX y QBCore, los nombres de callback son una fila en el mapa de funciones.
Lista de verificación
| Síntoma | Solución |
|---|---|
| El resultado es nil | Comprueba que el nombre coincida exactamente en ambos lados |
| Nunca responde | Asegúrate de que el archivo del servidor está en el manifiesto y el recurso se inició |
| Error en la consola del servidor | Arréglalo; un callback que falla no envía respuesta |
| ESX o QBCore: sin respuesta en algunas rutas | Llama a cb(...) en cada rama |
| ox_lib: resultado nil | Añade return a la función lib.callback.register |
lib es nil |
Añade shared_script '@ox_lib/init.lua' al manifiesto |
Respuestas rápidas
¿Cuál es la diferencia entre un callback y un evento?
Un evento envía un mensaje y no espera una respuesta. Un callback pregunta al otro lado y obtiene un valor de vuelta, así que el cliente puede usar datos que solo el servidor conoce.
¿Puedo usar callbacks de ox_lib en ESX o QBCore?
Sí. ox_lib es independiente del framework, así que lib.callback funciona en ESX, QBCore y QBox siempre que ox_lib esté iniciado y cargado por el script.
¿Por qué lib.callback.await detiene mi script un rato?
Espera la respuesta del servidor, así que cede el thread. Si el servidor nunca responde porque el callback falta o da error, el thread sigue esperando o falla con un error.
Scripts que evitan este problema
Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →
Quest CreatorUn editor visual de misiones y diálogos con NPC, nodo a nodo dentro del juego.Ver script →
Pawn Shop AppUn mercado de empeños entre jugadores dentro de lb-phone.Ver script →