2015-02-11 58 views
2

我想寫一些DOM解析代碼從node REPL environment運行。下面是一個SSCCE:如何從節點解析DOM與jsdom REPL

"use strict"; 

var jsdom = require("jsdom"); 

var html="<a></a>"; 

function parse(html, x) { 
    jsdom.env(html, function(errors, window) { 
     x.window = window; 
    }); 
} 

var x = {}; 
parse(html, x); 
console.log(x.window); 

的想法是,調用parse功能後,我將不得不解析DOM可以在我的x對象。

當我把上面的代碼在一個文件j.js,並從REPL加載它,我得到:

> .load j.js 
> "use strict"; 
'use strict' 
> var jsdom = require("jsdom"); 
undefined 
> var html="<a></a>"; 
undefined 
> function parse(html, x) { 
...  jsdom.env(html, function(errors, window) { 
.....   x.window = window; 
.....  }); 
... } 
undefined 
> var x = {}; 
undefined 
> parse(html, x); 
undefined 
> console.log(x.window); 
undefined 
undefined 
> 

爲什麼代碼不能分配x.window財產?

+1

@jsalonen我想,最終,獲得對應'html'變量的DOM對象,並做一些樹導航。這是一個SSCCE。也許有一種更好的方式來使用'jsdom'來獲取DOM我剛剛提出了這個'parse'函數作爲一種抽象出jsdom邏輯的方法,並且有一種方法可以將值傳遞給調用上下文。 – 2015-02-11 21:00:17

回答

1

jsdom.env回調得到異步評估。這意味着在大多數情況下(可能總是)console.log(x.window)x.window = window;分配之前被執行。

最簡單的解決方法是通過你的任務後執行的回調函數:

... 

function parse(html, x, done) { 
    jsdom.env(html, function(errors, window) { 
     x.window = window; 
     done(); 
    }); 
} 

var x = {}; 

parse(html, x, function() { 
    console.log(x); 
}); 
+0

好吧,基本上這樣做,對象和參數'x'是多餘的。有沒有一種習慣用於將這個異步接口轉換爲一個同步接口,例如:'var window = parse(html)'? – 2015-02-11 21:39:32

+1

的確,您不需要將'x'作爲參數傳遞給'parse',因爲它已經可以從外部作用域看到。然而,編寫像'var window = parse(html)'這樣的代碼需要你從異步轉換爲同步,這在節點中通常是一個壞主意:除非你使用類似節點光纖的東西(比如說通過同步)阻止所有其他執行,直到完成同步分析。 就個人而言,我寧願嘗試使用流程並採用異步編程風格 - 它通常編寫節點程序的方式。 – jsalonen 2015-02-11 21:49:05