2016-01-03 45 views
3

我一直在努力,現在用於解析API有點JSON的,它是當我用空返回值解析JSON在使用XMLHttpRequest的

xmlHttp.open('GET', url, false); 

所有工作但當我後來想用擴大我的代碼超時爲我的函數開始返回空值的請求。

這是函數做實際的解析:

xmlHttp.onreadystatechange = function() { 
     if (xmlHttp.readyState == 4) { 
      if (xmlHttp.status == 200) { 
       obj = JSON.parse(xmlHttp.responseText); 
       console.log(obj); 
      } 
     } 
    }; 

當我登錄的對象返回這裏使用的console.log我得到的JSON打印到控制檯正常,但後來在我的功能,我返回obj變量,但它總是空的。

這裏是全功能:

static Parse(url: string): Object{ 
    Asserts.isUrl(url, 'URL is invalid'); 
    var obj = new Object(); 
    var xmlHttp = new XMLHttpRequest(); 

    xmlHttp.onreadystatechange = function() { 
     if (xmlHttp.readyState == 4) { 
      if (xmlHttp.status == 200) { 
       obj = JSON.parse(xmlHttp.responseText); 
       //console.log(obj); 
      } 
     } 
    }; 

    xmlHttp.open('GET', url, true); 
    xmlHttp.timeout = 2000; 
    xmlHttp.ontimeout = function() { 
    xmlHttp.abort(); 
    throw new Error("Request Timed Out."); 
    }; 
    xmlHttp.send(); 

    return obj; 
} 

我首先想到的是它必須是與JavaScript中的範圍,但現在這裏被卡住沒有進步了幾個小時,我無言以對了。

正如我在xmlHttp.onreadystatechange = function()中所提到的,console.log實際上記錄了正確的值。只是在函數開始時創建的obj變量沒有獲取值。

回答

3

AJAX是異步的。這意味着onreadystatechange函數將在很晚的階段被調用,可能在您已經從Parse方法返回後。所以你不應該試圖從Parse方法返回obj。您寧願讓Parse方法採用一個附加參數來表示您將在onreadystatechange事件中調用的回調函數,並將結果對象傳遞給它。

這裏就是我的意思是:

static Parse(url: string, done: (obj: any) => void): void { 
    Asserts.isUrl(url, 'URL is invalid'); 
    var xmlHttp = new XMLHttpRequest(); 

    xmlHttp.onreadystatechange = function() { 
     if (xmlHttp.readyState == 4) { 
      if (xmlHttp.status == 200) { 
       var obj = JSON.parse(xmlHttp.responseText); 
       // Pass the resulting object to the callback function 
       done(obj); 
      } 
     } 
    }; 

    xmlHttp.open('GET', url, true); 
    xmlHttp.timeout = 2000; 
    xmlHttp.ontimeout = function() { 
     xmlHttp.abort(); 
     throw new Error("Request Timed Out."); 
    }; 
    xmlHttp.send(); 
} 

,這裏是你如何調用Parse功能:

Parse('http://foobar', function(obj) => { 
    // TODO: do something with obj here 
    console.log(obj); 
}); 

所以基本上當你正在編寫一個使用AJAX的異步調用,你應該停止JavaScript應用程序按順序函數思考,您將依次調用並返回值。你應該開始考慮回調。

+0

我將如何使函數等待onreadystatechange並返回正確的值?還是有另一個更好的解決方案? – BrokenProgrammer

+0

如果你讓它等待,那麼你絕對會殺死AJAX的目的是異步的。有關如何編寫Parse函數的示例,請參閱我的更新答案,以便它不返回任何值,而是使用回調。 –

+0

我正在構建一個正朝着API工作的庫。所以這種方法對於這個目的仍然有好處?你也有任何資源可以閱讀關於同步和異步之間的區別嗎? – BrokenProgrammer

0

你需要一個回調傳遞給函數:

static Parse(url: string, onSuccess: Function): Object{ 
    Asserts.isUrl(url, 'URL is invalid'); 

    var xmlHttp = new XMLHttpRequest(); 

    xmlHttp.onreadystatechange = function() { 
     if (xmlHttp.readyState == 4) { 
      if (xmlHttp.status == 200) { 
       var obj = new Object(); 
       obj = JSON.parse(xmlHttp.responseText); 
       onSuccess(obj) 
      } 
     } 
    }; 

    xmlHttp.open('GET', url, true); 
    xmlHttp.timeout = 2000; 
    xmlHttp.ontimeout = function() { 
    xmlHttp.abort(); 
    throw new Error("Request Timed Out."); 
    }; 
    xmlHttp.send(); 

} 

,並調用函數回調參數。