在Javascript函数执行之前解析XML

时间:2017-08-14 09:40:37

标签: javascript xml parsing

我有一个外部XML文件,我想使用Javascript解析,但在执行另一个Javascript函数之前。我想将XML文件中的值存储在全局对象中。问题是我正在异步解析我的XML,因为不推荐使用同步解析。 Javascript函数在解析XML之前执行,因此我得到一个错误,因为全局变量是undefined

我尝试在一个Javascript文件中调用解析XML文件的函数,然后使用defer属性在另一个文件中调用该函数。但这确实有效,因为解析器仍然在执行所有脚本后执行。我很难过!我也尝试在Javascript函数上使用setTimeout()方法,但最后也会生成未定义的值。

我已经阅读了有关堆栈溢出的几个问题,这些问题与执行脚本的顺序有关。我会说这个问题让我对执行顺序有很多了解。

注意:我的脚本比这里显示的要多得多,所以我只添加了一些基本内容来说明我如何解析XML文件并将值存储为未定义。

更新:我已经用这种方式编写了解析器,以便我可以以中立的方式使用。解析器被多次使用,并且每次根据使用情况发生不同的事件。这就是我没有向onreadystatechange函数添加特定函数的原因。

我正在使用XML DOMXMLHttpRequest来解析我的XML文件。

// Parser
function load_prs( data_func , loc , tag )
{
var parsreq = new XMLHttpRequest() ;

parsreq.onreadystatechange = function() {
if ( (parsreq.readyState === 4) && (parsreq.status === 200) )
   {
   var xml = parsreq.responseXML ;
   var listing = xml.getElementsByTagName(tag) ;
   var list = listing[0].children ;

   // Call a specific function using the data_func argument
   data_func(list) ;
   }
} ;

parsreq.open("GET" , loc + ".xml" , true) ;
parsreq.send() ;
}

调用要解析的函数:

load_prs(load_playlist , "nd/playlist" , "playlist") ;

函数load_playlist()将XML值分配给全局对象:

// The global object with name/value pairs
var playlist_obj = { band: "" , album: "" , title: "" } ;

// Array for storing playlist_obj
var playlist = [] ;

// Function to get values from the XML document
function get_val( tar , tag ) { return tar.getElementsByTagName(tag)[0].childNodes[0].nodeValue ; }

// Function passed to load_prs()
function load_playlist( list )
{
var px ;
var plen = list.length ;

// Loop through each item in the XML document and get values
for ( px = 0 ; px < plen ; px++ )
   {
   playlist_obj.band = get_val(list[px] , "band") ;
   playlist_obj.album = get_val(list[px] , "album") ;
   playlist_obj.title = get_val(list[px] , "title") ;

   // Push playlist_obj to the global array for later use
   playlist.push(playlist_obj) ;
   }
}

我的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<playlist>
<track>
   <band>Desecresy</band>
   <album>Stoic Death</album>
   <title>Funeral Odyssey</title>
</track>
<track>
   <band>Catacombs</band>
   <album>In the Depths of R'lyeh</album>
   <title>Where No Light Hath Shone...</title>
</track>
</playlist>

当我尝试调用另一个访问同一脚本中的全局对象的函数时,我得到了未定义的值。 var t会返回undefined,因为load_band()会在load_prs()之前执行。

load_prs(load_playlist , "nd/playlist" , "playlist") ;
function load_band() { var t = playlist[0].band ; }
load_band() ; // var t returns undefined

1 个答案:

答案 0 :(得分:0)

好吧,我想给Martin Honnen一个答案但是,他似乎无法使用。所以我要回答自己。但Martin Honnen确实回答了我的问题(请参阅评论)。虽然Promises本来是一个很好的解决方案,但我觉得答案可能更简单,无需添加更多代码并使情况比现有情况更复杂。

所以答案其实很简单。通过将load_band()函数直接添加到load_playlist()函数中,我的变量按照我想要的顺序得到它们的值。我只需要确保调用的所有函数都是从传递给解析函数的函数中调用的。我不得不广泛地重写我的代码,但这是值得的。现在我的load_prs()函数可以多次使用,作为中性函数。它获取值,然后可以使用这些值执行不同的操作,具体取决于意图,以及传递给它的特定函数。现在示例如下所示:

function load_playlist( list )
{
var px ;
var plen = list.length ;
for ( px = 0 ; px < plen ; px++ )
   {
   playlist_obj.band = get_val(list[px] , "band") ;
   playlist_obj.album = get_val(list[px] , "album") ;
   playlist_obj.title = get_val(list[px] , "title") ;
   playlist.push(playlist_obj) ;
   }
load_band() ;
}

function load_band() { var t = playlist[0].band ; }
load_prs(load_playlist , "nd/playlist" , "playlist") ;

注意:当我让这个例子工作时,我发现我的playlist数组中的对象都是相同的。这是因为我使用的是具有名称值对的全局对象,并尝试在不同的时间为其赋予不同的值。

var playlist_obj = { band: "" , album: "" , title: "" }

我能够通过使用对象构造函数来解决这个问题。

// Object constructor
function pobj( b , a , t )
{
this.band = b ;
this.album = a ;
this.title = t ;
}

// Create local variables
var band = get_val(list[px] , "band") ;
var album = get_val(list[px] , "album") ;
var title = get_val(list[px] , "title") ;

// The new keyword creates a new object
playlist_obj = new pobj(band , album , title) ;

// Store the new object in the global array
playlist.push(playlist_obj) ;