在承诺链中等待DOM元素中的突变
我在Node.js中制作了一些网页抓取工具,用PhantomJS拍摄了一个网站上出现的地图。
但是,页面打开后,会在地图所在的位置显示加载消息。 地图准备就绪后,消息消失( visibility: hidden
),并显示地图。
正因为如此,我不能调用page.render()
直到hidden
#loader
(或者我会得到一个加载消息的图片,而不是很酷)。
// ... Open the page .then(function(content) { return page.evaluate(function() { // Wait for #loading to get hidden somehow ... var clipRect = document.getElementById('map').getBoundingClientRect(); return { top: clipRect.top, left: clipRect.left, width: clipRect.width, height: clipRect.height }; }); }) // Render and process the picture ...
我考虑使用突变观察者 ,但无法find使用它的方法,因为我处于承诺链中 ,并且事件侦听器不能按我的要求工作。
我也经常检查visibility
属性,直到它被隐藏,正如这里所解释的,但PhantomJS通过Node的控制台报告:
TypeError: null is not an object (evaluating 'child.transform')
另外,如果可能的话,我想避免这种解决方法,因为它们非常耗费CPU资源。
任何想法如何等待#loader
在这些情况下hidden
?
我终于解决了这个问题,感谢phantomjs-node
的mantainer, amir20 ,所以都归功于他。 正如他在这个问题上解释的:
waitFor
期望返回一个值。 但evaluate
返回一个Promise
。 所以这就是为什么它不工作。 这不是模块的问题,而是waitFor
问题。 由于一切都是asynchronous执行的,所以你必须等待这个值。
有问题的function(由他创build)如下:
function waitUntil(asyncTest) { return new Promise(function(resolve, reject) { function wait() { asyncTest().then(function(value) { if (value === true) { resolve(); } else { setTimeout(wait, 100); } }).catch(function(e) { console.log('Error found. Rejecting.', e); reject(); }); } wait(); }); }
因此,适用于我的具体示例,应该这样使用:
waitUtil(function() { return sitepage.evaluate(function() { return document.querySelectorAll('#loader').style.visibility == "hidden"; }) }).then(function(){ // #loading is now hidden return page.evaluate(function() { var clipRect = document.getElementById('map').getBoundingClientRect(); return { top: clipRect.top, left: clipRect.left, width: clipRect.width, height: clipRect.height }; }); }) // Render and process the picture ...