我正在使用HTML和Javascript创建一个Facebook游戏,我刚刚完成了排行榜的构建,其中列出了每个玩家的姓名和排名。此表包含从Facebook的游戏评分API返回的数据。
这非常有效,但我也想奖励那些在积分榜上排名提高的球员。
我计划这样做:
- 当游戏加载时,我运行一个名为
updateTable();
的函数用玩家的分数和排名填充排行榜从对Facebook数据库的API调用接收 - 当玩家开始玩游戏时,我会将他们等级的副本存储在一个单独的隐藏div中
- 当游戏结束时,如果玩家获得了新的高分,那么它被输入到数据库中。发生这种情况后,我就跑再次
updateTable();
更新排行榜 - 然后我运行一个名为
compareRanks();
的函数,它将玩家的新等级与我存储在隐藏分区中的等级
如果新的排名比存储的排名低,那么他们已经在排行榜上排名上升,我会奖励他们每上升一个位置100枚硬币。
例如:
玩家A开始游戏,排名第五(因此"5"存储在一个隐藏的div中)。当玩家A完成游戏时,排行榜会更新,玩家A现在排名第二(因此玩家跳了3位)。
为了计算奖励应该是多少,我想从第二个变量中减去第一个变量(5-2=3),玩家A超过了其他3名玩家,所以他们的奖励将是3 x 100金币。
我遇到的问题是,当我运行compareRanks();
时,新的等级一直显示为与存储的等级相同的数字,尽管我知道玩家已经提高了他们的等级。
我敢肯定这是由于updateTable();
在与数据库完全交互之前就已经获取了新的排名。我已经通过分离功能进行了测试,通过点击按钮使compareRanks();
运行,当我这样做时,我完成了一个游戏,提高了我的排名,在updateTable();
运行后等待几秒钟,然后点击按钮,两个排名显示不同,这是正确的。所以我认为compareRanks();
只需要等待updateTable();
完全完成即可运行。
这就是我的功能布局:
updateTable(){
//code here interacts with the database/makes a call using Facebook's API,
//and populates the leaderboard table with the returned data
}
在新游戏开始时,玩家的当前等级存储在隐藏的分区中。
游戏结束后,再次运行updateTable();
,然后运行compareRanks();
:
compareRanks(){
//code here grabs the stored rank from the hidden div
//code here grabs the newly updated rank and compares the two.
}
我读过关于使用回调的答案,但我无法让它们发挥作用。我试过做这样的事情:
updateTable(){
{
//code here interacts with the database/makes a call using Facebook's API,
//and populates the leaderboard table with the returned data
}
compareRanks();
};
但是当compareRanks();
运行时,新的秩仍然显示为与旧秩相同。updateTable();
在运行时正确地更改了排行榜上的排名,所以我认为compareRanks();
只是在updateTable();
完全完成之前运行的。
如果能帮我解决这个问题,我将不胜感激,提前谢谢!
实现这一点的一个好方法是使用Javascript Promises。它们允许您在不嵌套多个回调函数的情况下执行异步操作。
function first (parameter){
return new Promise(function(resolve,reject){
//Do async stuff, maybe some ajax
//When async stuff is finished:
resolve(async_data);
//Or when something went wrong:
reject(error);
}
}
function second(parameter){
return new Promise(function(resolve,reject){
//Do async stuff, maybe some ajax
//When async stuff is finished:
resolve(async_data);
//Or when something went wrong:
reject(error);
}
}
//You can then use:
first(data).then(second(async_data)).then(function(async_data){
//Here would be the point where both functions finished after eachother!
}).catch(function(error){
//Hey, one of my promises was rejected! Maybe I should handle that error :)
});
这有几个优点。您可以将任意多的函数和操作放入.then
的链中,而无需嵌套大量的回调函数。您也可以使用.catch()
访问reject()
调用。你应该仔细阅读Promises的文档,因为还有更多的功能对你来说应该很有趣。
如果你不想参与Promises(它们让你的代码更干净,因为它们是可组合的,所以你可以创建非常清晰的Promises链),你可以研究一些其他可以使用回调的awnser(对于这样一个小用例来说没那么糟糕)。
这里有一篇关于它的好文章:文章:JavaScript Promises
基本上回调是作为参数传递给另一个函数的函数。JavaScript之所以能够做到这一点,是因为函数是一流的对象。
现在,因为updateTable
将调用db/FB API,所以您需要在该操作的回调中调用回调。我不知道该操作的正确语法,所以我的示例使用伪代码。
function updateTable(callback) {
FBAPI.get(something, function (data) {
// do things
callback();
});
}
updateTable(compareRanks);
注意,如果compareRanks
需要访问API中的数据,您也可以将数据传递给回调:
callback(data);
最好使用javascript的new Promise
对象-
Promise对象用于延迟和异步计算。Promise代表一项尚未完成的操作,但有望在未来完成。
new Promise(executor);
new Promise(function(resolve, reject) { ... });
查看此链接以获取更多帮助-https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
我认为Aless80的评论是你答案的关键。我不知道Facebook API是什么样子的,但每当你像这样与数据库或网络服务器交互时,API调用通常会有一个回调,你可以在其中处理服务器可能返回给你的任何内容。
例如,我正在处理的一个简单的web服务器处理通过浏览器的AJAX调用发送的请求。我使用Jquery来实现这一点,但结构应该大致相同。
var dataObject = {};
var dataID = "1234";
$.ajax({
type: "GET", // basic http get request
url: "http://www.mywebserver.com/get-data/" + dataID,
crossDomain: true
}).done(function(response){
// this function runs after the webserver has received our GET request and handled it
// response contains the data we got back from mywebserver
dataObject = response;
});
DoSomething(dataObject);
这里发生的情况是,"DoSomething()"将在dataObject包含数据库返回的任何数据之前激发!因此,如果我们想对返回的数据进行处理,我们应该在ajax请求的"回调"中调用函数,如下所示:
var dataObject = {};
var dataID = "1234";
$.ajax({
type: "GET", // basic http get request
url: "http://www.mywebserver.com/get-data/" + dataID,
crossDomain: true
}).done(function(response){
//dataObject = response;
//DoSomething(dataObject);
DoSomething(response);
});
这个例子中注释掉的东西是为了清楚起见,当然,我们希望避免不必要地传递变量:)
我还强烈建议研究JavaScript回调。它们一开始很难理解,但Node.js基本上是建立在这个概念的基础上的,因此非常值得熟悉它们。