Javascript连续承诺没有被解雇

时间:2017-07-20 11:09:11

标签: javascript node.js promise phantomjs

我正在使用PhantomJS使用node.js登录网站。之后我想发一个HTTP请求来获取带有数据的json。我的代码如下:

phantom.create()
.then(function (ph) {
    this.ph = ph;
    return ph.createPage();
})
.then(function (page) {
    this.page = page;
    return page.open('https://example.com');
})
.then(function (status) {

    if ( status === "success" ) {
        return this.page.evaluate(function() {
              document.querySelector("input[name='j_username']").value = 'example@example.net';
              document.querySelector("input[name='j_password']").value = 'example';
              console.log('Submitting logging...');
              document.querySelector("input[name='submit']").click();
        });
   } else {
       return null;
   }
})
.then(function() {
    console.log("Logged in!");

    this.page.property('onResourceRequested', function(requestData, networkRequest) {
        //This event is fired 40 times, only one is interesting to me the one that has the text maps.json in it
        if (requestData.url.indexOf('maps.json') !== -1) {
            return {headers: requestData.headers, url: requestData.url};
        }
    });
});
.then(function (data) {
    //This then block is only fired once, with the first call of the first url in previous then block and data is null
    if (data) {
        // This code block is never fired because this then is only called once with data=null
        console.log(data);

        request.get({
                uri: data.url,
                headers: data.headers
        }, function(err, res, body){
          if (!err) {
                callback(null, res.headers);
          } else  {
                  console.log("Error getting data from URL: "+ err);
                  callback(true, null);
          }
        }); 
    }
});

此后续承诺肯定有问题,因为倒数第二个块中的this.page.property('onResourceRequested'...函数被触发40次(登录后在网站内调用每个url一个),但最后then仅被触发一次(当请求第一个URL时)。

我想从一个具体网址(网址中包含maps.json的网址)获取数据,该网址是电话号码32.

我做错了什么?如果我的电话完成,我该如何解除最后一次?

编辑:

按照@ charlieetfl的建议,我把代码搞砸了以下内容,但仍然没有工作......:

phantom.create()
.then(function (ph) {
    this.ph = ph;
    return ph.createPage();
})
.then(function (page) {
    this.page = page;
    return page.open('https://example.com');
})
.then(function (status) {

    if ( status === "success" ) {
        return this.page.evaluate(function() {
              document.querySelector("input[name='j_username']").value = 'example@example.net';
              document.querySelector("input[name='j_password']").value = 'example';
              console.log('Submitting logging...');
              document.querySelector("input[name='submit']").click();
        });
   } else {
       return null;
   }
})
.then(function() {
    console.log("Logged in!");
    return new Promise(function(resolve, reject) {
        this.page.property('onResourceRequested', function(requestData, networkRequest) {
            //This event is fired 40 times, only one is interesting to me the one that has the text maps.json in it
            if (requestData.url.indexOf('maps.json') !== -1) {
                resolve({headers: requestData.headers, url: requestData.url});
            }
        });
    });
});
.then(function (data) {
    //This then block is only fired once, with the first call of the first url in previous then block and data is null
    if (data) {
        // This code block is never fired because this then is only called once with data=null
        console.log(data);

        request.get({
                uri: data.url,
                headers: data.headers
        }, function(err, res, body){
          if (!err) {
                callback(null, res.headers);
          } else  {
                  console.log("Error getting data from URL: "+ err);
                  callback(true, null);
          }
        }); 
    }
});

编辑:21/07/2017 10:52 UTC。

我将代码更改为新代码:

phantom.create().then(function(ph) {
  ph.createPage().then(function(page) {
    page.open('https://example.com/').then(function(status) {
          if ( status === "success" ) {
            page.evaluate(function() {
                  document.querySelector("input[name='j_username']").value = 'example';
                  document.querySelector("input[name='j_password']").value = 'example';
                  console.log('Submitting logging...');
                  document.querySelector("input[name='submit']").click();
            }).then(function(){

                  page.property('onResourceRequested', function(requestData) {
                        if (requestData.url.indexOf('geomaps.json') !== -1) {
                            console.log(JSON.stringify(datos));
                            request.get({
                                    uri: requestData.url,
                                    headers: requestData.headers
                            }, function(err, res, body){
                                  if (!err) {
                                        console.log(res.headers);
                                  } else  {
                                        console.log("Error getting data from website: "+ err);
                                  }
                            });

                        }
                  });

            });

          }
    });
  });
});

结果相同。 console.log(JSON.stringify(datos));正在被解雇,但是request.get永远不会被解雇。

我的事情可能与在Promises中触发异步功能有关吗?

EDIT 21/07/2017 11:09 UTC

更多测试。如果我简化了page.property(' onResourceRequested'代码块,我看到then()只被调用一次,并且在每次调用收到requestData之前...

enter image description here

我有点困惑,我现在还不知道如何处理这个......

1 个答案:

答案 0 :(得分:0)

我终于解决了这个问题。 page.property('onResourceRequested'在PhantomJS进程中执行。 PhantomJS不与节点共享任何内存或变量。因此,使用javascript中的闭包来共享函数之外的任何变量是不可能的。 使用page.on('onResourceRequested'代替解决问题!