【问题标题】:Wait in a promise chain for a mutation in a DOM element在承诺链中等待 DOM 元素中的突变
【发布时间】:2016-03-27 23:33:24
【问题描述】:

我正在 Node.js 中制作某种网络爬虫,它会拍摄一张出现在带有 PhantomJS 的网站上的地图。

然而,一旦页面被打开,一个正在加载消息就会出现在地图应该在的地方。地图准备好后,消息消失 (visibility: hidden) 并显示地图。

因此,在#loaderhidden 之前,我无法调用page.render()(否则我会得到加载消息的图片,不酷)。

// ... 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 ...

我考虑过使用mutation observer,但找不到使用它的方法,因为我处于承诺链中,并且事件侦听器无法按我的意愿工作。

我还尝试经常检查 visibility 属性,直到它被隐藏,正如 here 所解释的那样,但 PhantomJS 通过 Node 的控制台报告:

TypeError: null is not an object (evaluating 'child.transform')

此外,如果可能的话,我想避免这种变通方法,因为它们非常占用 CPU。

关于在这种情况下如何等待#loader 获得hidden 的任何想法?

【问题讨论】:

    标签: javascript node.js promise phantomjs mutation-observers


    【解决方案1】:

    感谢phantomjs-node 的管理员amir20,我终于解决了这个问题,所以感谢他。正如他在this issue 中解释的那样:

    waitFor 期望返回一个值。但是evaluate 返回一个Promise。所以这就是它不起作用的原因。这不是模块的问题,而是waitFor 的问题。由于一切都是异步执行的,因此您必须等待该值。

    有问题的函数(由他创建)如下:

    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 ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 2018-03-19
      • 2020-01-01
      • 2021-11-09
      • 2018-10-17
      • 2019-04-29
      • 2016-04-13
      相关资源
      最近更新 更多