2017-08-11 96 views
0

我仍然是一個Javascript的noob,我一直在努力包裝頭腦的一件事是迫使同步成爲一種主要是異步編程語言。關於Javascript回調函數/承諾的混淆

我有一個函數,加載一個體面的大小JSON文件和利用此函數返回的另一個函數。

我已經閱讀了很多關於類似問題的其他線索,並繼續看到非常不同的解決方案,我只是好奇處理這個問題的最佳方法是什麼。

構造函數調用兩個功能 -

class Guild extends MapObject { 
constructor(x,y,floor,type,name) { 
    super(x,y,floor); 
    this.levels = []; 
    this.type = type; 
    this.name = name; 
    this.guildSelector(); 
    this.addLevels(this.name); 
    this.setTip(); 
} 
加載的JSON,並將它作爲目前前 this.guildData填充了JSON運行它造成 this.guildData

guildSelector(){ 
    var oReq = new XMLHttpRequest(); 
    this.guildData = null; 

    oReq.onload = reqListener; 
    oReq.open("get", "/json/guilds.json", true); 
    oReq.send(); 

    function reqListener() { 
     this.guildData = JSON.parse(this.responseText); 
     console.log(this.guildData); 
     return this.guildData; 
    } 
} 

addLevels功能

guildSelector功能崩潰,因爲它找不到null的.guilds。

addLevels(name) { 

    if(name == "default"){ 
     this.name = "lowerSchoolOfEndurance"; 
    } 

    console.log(this.guildData); 

    this.guildData.guilds.forEach(function(guild) { 
     console.log(guild.name); 
     if(guild.name == name){ 
      for(var i = 1; i <= guild.levels.length; i++){ 
       var guildStats = guild.levels[i-1]; 
       for (var k in guildStats) { 
        console.log("Level "+i+" of the guild "+name+" increases "+k+" stat by "+guildStats[k]); 
        this.levels.push(guild.levels[i-1]); 
       } 
      } 
     } 
    }); 
    return this.levels; 
} 

所以TL:DR將基本上,什麼是不觸發我的課,需要的JSON直到JSON加載要加載的最佳方式。

親切的問候, 伯爵Lemongrab

+0

*強制同步到一個主要的異步編程語言* - 這不適合你。您必須*擁抱該語言的異步性質。 – Pointy

+0

我明白,在一般意義上,但對於這個問題,這不完全是我在做什麼?當然,有些情況下需要強制同步行爲? 無論如何,你鏈接到的答案和羅布給出的答案很好地解決了我的問題,非常感謝:) –

回答

2

你應該使用Promise S:

guildSelector(){ 
    return new Promise((resolve, reject) => { 
     var oReq = new XMLHttpRequest(); 
     this.guildData = null; 

     oReq.onload = reqListener; 
     oReq.open("get", "/json/guilds.json", true); 
     oReq.send(); 

     function reqListener() { 
      this.guildData = JSON.parse(this.responseText); 
      resolve(this.guildData); 
     } 
    }) 
} 

然後改變你的構造利用了承諾:

this.guildSelector().then((guildData) => { 
    this.guildData = guildData; 
    this.addLevels(this.name); 
}); 
+0

謝謝!這工作完美。我對Promise的語法有點不確定,所以我想避免它們,但它似乎絕對值得更多的閱讀。仍然需要等5分鐘才能選擇這個作爲正確的答案,但我會:p –

+1

很高興幫助伯爵。承諾在很多不同的場景中都非常有用,絕對值得花一些時間學習。歡呼聲,祝你好運! :) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise –