如何仅在第一个功能完全完成后才 运行 第二个 Javascript 功能?

How to run second Javascript function only after first function fully completes?

我正在使用 HTML 和 Javascript 创建一个 Facebook 游戏,我刚刚构建了一个排行榜 table,其中列出了每个玩家的名字和 运行 k 号。此 table 填充了从 Facebook 的游戏得分 API 返回的数据。

这很完美,但我也想奖励玩家在 table 中提高他们的 运行k。

我打算这样做:

如果新的 运行king 比存储的 运行k 小,那么他们已经在排行榜上上升,他们每上升一个位置我就会奖励他们 100 个硬币。

例如:

玩家 A 开始游戏并获得第 5 名 运行(因此“5”存储在隐藏的 div 中)。 当玩家 A 完成游戏时,排行榜会更新,玩家 A 现在 运行 排名第二(因此玩家跳了 3 位)。

为了计算奖励应该是多少,我想从第二个变量中减去第一个变量 (5-2 = 3),玩家 A 超过了其他 3 名玩家,因此他们的奖励将是 3 x 100 金币。

我遇到的问题是,当我 运行 compareRanks(); 时,新的 运行k 一直显示为与存储的 运行k 相同的数字, 尽管我知道玩家已经提高了他们的 运行k.

我很确定这是因为新的 运行k 在 updateTable(); 与数据库完全交互之前被抓取了。我通过分离功能测试了这个,通过点击按钮使 compareRanks(); 运行,当我这样做时,我完成了一个游戏,改进了我的 运行k,等了几个updateTable(); 运行 秒后,然后单击按钮,两个 运行ks 显示不同,这是正确的。所以我认为 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
}

在新游戏开始时,玩家的当前 运行k 存储在隐藏的 div.

当游戏完成时 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(); 运行s 时,新的 运行k 仍然显示为与旧的 运行k 相同。 updateTable(); 在 运行s 时正确地改变了排行榜上的 运行ks,所以我认为 compareRanks(); 只是 运行ning 在 updateTable(); 完全完成。

如果能帮助解决此问题,我将不胜感激,在此先感谢您!

回调基本上是作为参数传递给另一个函数的函数。 JavaScript 可以做到这一点,因为函数是 first-class 个对象。

现在,因为 updateTable 将调用 db/FB API,您需要在 该操作的回调中调用回调 。我不知道该操作的正确语法,所以我的示例使用伪代码。

function updateTable(callback) {
   FBAPI.get(something, function (data) {
     // do things
     callback();
   });
}

updateTable(compareRanks);

请注意,如果 compareRanks 需要访问 API 中的数据,您也可以将数据传递给回调:

callback(data);

解决这个问题的一个好方法是使用 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(它们使您的代码更清晰,因为它们 可组合 因此您可以创建非常清晰的承诺链)您可以查看其他一些与回调一起工作的 awnsers(对于这么小的用例来说还不错)。

这是一篇很棒的文章:Article: JavaScript Promises

最好使用 new Promise 对象 javascript-

The Promise object is used for deferred and asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected in the future.

new Promise(executor);

new Promise(function(resolve, reject) { ... });

检查此 link 以获得更多帮助- https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

我认为 Aless80 的评论是您回答的关键。我不知道 Facebook API 是什么样子,但每当你与数据库或网络服务器交互时, API 调用通常会有一个回调,你可以在其中处理任何事情服务器可能 return 给你。

例如,我正在处理的一个简单的网络服务器处理通过来自浏览器的 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 包含任何由数据库 return 编辑的数据之前触发!因此,如果我们想对 returned 数据做一些事情,我们应该在 ajax 请求的 "callback" 中调用该函数,如下所示:

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 基本上是建立在概念之上的,因此非常值得熟悉它们。