Le callback serveur retourne nil : rappels ESX, QBCore et ox_lib
ESX.TriggerServerCallback, QBCore TriggerCallback et lib.callback.await retournent nil ? Comment chaque callback fonctionne sur le serveur et le client, et les raisons pour lesquelles ils ne retournent rien.
Un script client demande des données au serveur, et ce qui revient est nil, ou rien du tout :
SCRIPT ERROR: @my_script/client/main.lua:21: attempt to index a nil value (local 'result')Les callbacks serveur sont comment le client demande une question au serveur et reçoit une réponse. Chaque framework a le sien, et ox_lib en a un qui fonctionne partout. Cet article montre les trois et pourquoi ils retournent nil.
ESX
Enregistrez sur le serveur, déclenchez du client :
-- 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 fonction serveur reçoit source et cb, et vous passez la réponse à cb. Les arguments supplémentaires du client arrivent après cb. La fonction client reçoit ce que cb a envoyé.
QBCore
Les noms diffèrent, la forme est la même :
-- 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 ou QBCore est nil à l'intérieur du script, le callback ne s'enregistre jamais. Consultez ESX est nil et QBCore est nil.
ox_lib
Les callbacks ox_lib n'ont pas besoin de framework, et la réponse est une valeur de retour au lieu d'une fonction 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)Le deuxième argument de await est un délai en millisecondes entre l'appel et la réponse (utilisez false pour aucun). Les arguments pour le serveur le suivent :
local ok = lib.callback.await('my_script:buy', false, 'burger', 2)lib.callback.register('my_script:buy', function(source, item, amount)
-- ...
return true
end)Pour que le callback existe, le script charge ox_lib dans son manifeste :
shared_script '@ox_lib/init.lua'Sans lui, lib est nil : consultez ox_lib init.lua non trouvé.
Le serveur peut aussi appeler un client : lib.callback.await('name', playerId, ...) sur le serveur, avec lib.callback.register sur le client. Si vous préférez ne pas attendre, lib.callback('name', false, function(result) end) prend une fonction à la place.
Pourquoi un callback retourne nil
Presque tous les cas sont l'un de ceux-ci :
- Le nom ne correspond pas. Les noms de registre et de déclenchement doivent être identiques, y compris la casse. Une faute de frappe ne lève pas une erreur que vous remarquerez, cela ne répond jamais.
- Il n'est pas enregistré. Le fichier serveur ne s'est jamais exécuté : il est manquant de
server_scripts, la ressource ne s'est pas démarrée, ou elle a échoué avant d'atteindre la ligne d'enregistrement. - Une erreur sur le serveur, avant la réponse. Si la fonction serveur génère une erreur, par exemple
xPlayerest nil, la réponse n'est jamais envoyée. Vérifiez la console serveur, pas celle du client. - Vous n'appelez jamais
cbsur chaque chemin. Sur ESX et QBCore, une branche qui revient sans appelercb(...)laisse le client en attente :
-- 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)- Vous avez oublié
returnsur ox_lib. Une fonctionlib.callback.registerqui n'a pas dereturnrépondnil. - Vous appelez trop tôt. Un callback client déclenché au démarrage du script peut atteindre le serveur avant que son registre s'exécute, après un redémarrage par exemple. Déclenchez-le après le chargement du joueur.
- Styles mélangés. Un callback enregistré avec
lib.callback.registerne peut pas être appelé avecESX.TriggerServerCallback. Utilisez la paire correspondante.
Conseil : pour savoir quel cas vous avez, ajoutez un
Se protéger contre nil sur le client
Traitez la réponse comme quelque chose qui peut manquer :
local money = lib.callback.await('my_script:getMoney', false)
if not money then
return print('No answer from the server')
endPour les anciens frameworks, vérifiez l'argument avant de l'indexer :
QBCore.Functions.TriggerCallback('my_script:getJob', function(job)
if not job then return end
print(job)
end)Celui à utiliser
- Écrire pour un seul framework : son propre callback est bien.
- Écrire pour plusieurs frameworks, ou pour QBox : utiliser ox_lib, donc un callback fonctionne partout.
- Écrire du nouveau code :
lib.callbackretourne des valeurs et se lit comme une fonction normale, ce qui rend les erreurs plus faciles à repérer.
Si vous portez un script entre ESX et QBCore, les noms de callback sont une ligne dans la carte de fonction.
Liste de contrôle
| Symptôme | Correction |
|---|---|
| Le résultat est nil | Vérifiez que le nom correspond exactement des deux côtés |
| Ne répond jamais | Assurez-vous que le fichier serveur est dans le manifeste et la ressource a démarré |
| Erreur dans la console serveur | Corrigez-la ; un callback qui échoue n'envoie pas de réponse |
| ESX ou QBCore : pas de réponse sur certains chemins | Appelez cb(...) sur chaque branche |
| ox_lib : résultat nil | Ajoutez return à la fonction lib.callback.register |
lib est nil |
Ajoutez shared_script '@ox_lib/init.lua' au manifeste |
Réponses rapides
Quelle est la différence entre un callback et un événement ?
Un événement envoie un message et n'attend pas de réponse. Un callback demande à l'autre côté et reçoit une valeur en retour, de sorte que le client peut utiliser des données que seul le serveur connaît.
Puis-je utiliser les rappels ox_lib sur ESX ou QBCore ?
Oui. ox_lib est indépendant du framework, donc lib.callback fonctionne sur ESX, QBCore et QBox tant que ox_lib est démarré et chargé par le script.
Pourquoi lib.callback.await arrête-t-il mon script pendant un moment ?
Il attend la réponse du serveur, il cède donc le thread. Si le serveur ne répond jamais parce que le callback est manquant ou génère une erreur, le thread continue d'attendre ou échoue avec une erreur.
Des scripts sans ce problème
Advanced BoostingDu boosting de véhicules piloté par tablette : contrats de classe D à S+, crews et file d’attente en direct.Voir le script →
Quest CreatorUn éditeur visuel de quêtes et de dialogues PNJ, construit nœud par nœud en jeu.Voir le script →
Pawn Shop AppUn marché de prêt sur gage entre joueurs, directement dans lb-phone.Voir le script →