简体   繁体   English

AngularJS,Node.js,节点模块'phantom'...注入错误,angularjs试图加载我的指令+后缀

[英]AngularJS, Node.js, node module 'phantom'… Injection error, angularjs trying to load my directive + Suffix

When I load an AngularJS page it loads fine. 当我加载AngularJS页面时,它加载正常。 No console errors. 没有控制台错误。 Content shows as expected. 内容按预期显示。

When I load the same page from another app, using Node module 'phantom' it fails with error: 当我从另一个应用程序加载相同的页面时,使用节点模块'phantom'它失败并显示错误:

Error: [$injector:unpr] http://errors.angularjs.org/1.5.8/$injector/unpr?p0=WidgetsProvider%20%3C-%20Widgets%20%3C-%20dashboardWeightTableWidgetDirective 错误:[$ injector:unpr] http://errors.angularjs.org/1.5.8/$injector/unpr?p0=WidgetsProvider%20%3C-%20Widgets%20%3C-%20dashboardWeightTableWidgetDirective

From the angular site this link equates to: Unknown provider: WidgetsProvider <- Widgets <- dashboardWeightTableWidgetDirective 从角度站点,此链接等同于: Unknown provider: WidgetsProvider <- Widgets <- dashboardWeightTableWidgetDirective

Please notice the directive name. 请注意指令名称。 " dashboardWeightTableWidgetDirective ". dashboardWeightTableWidgetDirective ”。 The directive is named, and referred to everywhere in my code as: " dashboardWeightTableWidget ". 该指令已命名,并在我的代码中随处可见:“ dashboardWeightTableWidget ”。

What is happening is that it is hitting this line in angular.js file: 发生的事情是它在angular.js文件中击中了这一行:

$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
function $CompileProvider($provide, $$sanitizeUriProvider) {
  var hasDirectives = {},
      Suffix = 'Directive',
      COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
      CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
      REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;

and then trying to use that altered name to do what looks like a dependency injection. 然后尝试使用该更改的名称来执行看起来像依赖注入的操作。 But this is a directive. 但这是一个指令。 Definition showing below. 定义如下。

angular.module('directives')
    .directive('dashboardWeightTableWidget', function (Data, Widgets, $interval, $window, $q) {

Again, this only happens when I am trying to render the page through phantom, using the node module that comes with this command: npm install phantom 同样,这只发生在我尝试使用此命令附带的节点模块通过幻像呈现页面时: npm install phantom

My relevant phantom code looks like this: 我的相关幻像代码如下所示:

const phantom = require('phantom');
let _ph;

exports.initPhantom = function() {
    phantom.create().then(ph => {
        _ph = ph;
 })
}

exports.processPage = function(conf) {
    return new Promise(function (resolve, reject) {
    console.log("creating phantom page ...");

    let _page, _interval, _pageReady;
    let _outObj = _ph.createOutObject();

    return _ph.createPage().then(function (page) { ....
        return _page.open(conf.options.viewerUrl);
    }).then (function(){
        setTimeout(() => {
              return _page.render(conf.options.filePath).then(function (status)                                                                       {
                   page.close();
              })

...

One additional comment: I can't figure out how to get into the loading page client-side code during the phantom render call. 另外一条评论:我无法弄清楚如何在幻像渲染调用期间进入加载页面客户端代码。 If I could do that, then I could step through the code and possibly see what is broken during the rendering. 如果我能做到这一点,那么我可以逐步完成代码并可能看到渲染过程中出现的问题。 If anyone knows this, I would be grateful for that answer too. 如果有人知道这一点,我也会对这个答案表示感谢。 You know, "teach a man to fish". 你知道,“教人钓鱼”。

let processPage = function(conf) {

  return new Promise(function (resolve, reject) {
    let instance = null;
    let phInstance = null;
    let reportPage = null;
    console.log("creating phantom page ...");

    let _outObj = _ph.createOutObject();

    return _ph.createPage()
      .then(function (page) {
        reportPage = page;
        _outObj.urls = [];
        _outObj.pageReady = false;

        page.property("customHeaders", {
          "Authorization": conf.options.authorization
        });
        page.property("paperSize", {
          //format: "Letter",
          format: "A4",
          margin: {
            top: '0.75in',
            left: '0.52in',
            bottom: '0.75in',
            right: '0.52in'
          }
        });
        page.property('setting', {
          resourceTimeout: 60000, // times out after 1 minute
          javascriptEnabled: true,
        });
        page.on('onConsoleMessage', function (msg, out) {
          console.log("on console msg ");
          console.log(msg);
          // should be 0 when page Widhgets are all loaded
          var loaded = msg.indexOf('getSeriesLoadingCount') > -1 ? true : false;
          if (loaded) {
            console.log('Message from console: ', msg, loaded);
            out.pageReady = true;
            _outObj = out;
          }
        }, _outObj);
        page.on('onResourceRequested', function (requestData, networkRequest, out) {
          // console.log('Request ' + JSON.stringify(requestData, undefined, 4));
          out.urls.push(requestData.url);
        }, _outObj);
        page.on("onError", function (msg, trace) {
          console.log("Error recorded: ", msg);
          trace.forEach(function (item) {
            console.log('  ', item.file, ':', item.line);
          });
        });
        page.on("onResourceError", function (resourceError) {
          page.reason = resourceError.errorString;
          page.reason_url = resourceError.url;
          console.log("Resource Error:", resourceError.errorString);
          console.log("Resource Url:", resourceError.url);
        });
        return page.open(conf.options.viewerUrl);

      })
      .then((status) => {
        let _pageReady = false;
        let _nbTrials = 0;
        // this setInterval loop is here to cycle through and check for the page being ready. It uses the PhantomJS event
        // property called 'onConsoleMessage'. This setting can be found above. It is a listener. In that listener we are
        // watching for a string that has a value of 'getSeriesLoadingCount' when the listener sees this text, it sets the
        // pageReady value to true. then this loop lets the code inside run. Primarily the rendering of the page to a file
        // in the temp directory of the server.
        _interval = setInterval(() => {
          _outObj.property('pageReady').then(function (ready) {
            if (ready === true) {
              clearInterval(_interval);
              return reportPage.render(conf.options.filePath).then(function (status) {
                reportPage.close();
                if (status) {
                  console.log('viewerUrl', conf.options.viewerUrl);
                  resolve(conf);
                } else {
                  console.log("cannot render page");
                  reject(conf);
                }
              });
            } else {
              ++_nbTrials;
              // 2 minutes
              if (_nbTrials >= 40) {
                return reject("too long generating the report");
              }
            }
          });
        }, 300);
      })
      .catch(error => {
        console.log("MAIN CATCH ERROR");
        console.log(error);
        reject(error);
      });
  });
}

Self Answer: 自答:

Ultimately I had a file inclusion issue. 最终我有一个文件包含问题。 Which is really inconsequential at this point. 在这一点上,这真的无关紧要。 I do think, however, there are 3 points worthy of taking away from my journey. 不过,我确实认为,有三点值得从我的旅程中拿走。

Unknown provider: WidgetsProvider <- Widgets <- dashboardWeightTableWidgetDirective
  1. I thought this error was telling me I had a problem with dashboardWeightTableWidgetDirective. 我以为这个错误告诉我,我遇到了dashboardWeightTableWidgetDirective的问题。 To angular that is where the error is occurring. 发生错误的角度。 But what this error is actually telling me is that I have an error in the dashboardWeightTableWidget directive, and the error is that it cannot find the provider "Widgets". 但是这个错误实际上告诉我的是我在dashboardWeightTableWidget指令中有一个错误,错误是它无法找到提供程序“Widgets”。 Therefore, the actual problem was a bug in the file that was providing "Widgets". 因此,实际问题是提供“Widgets”的文件中的错误。

  2. As a part of the internal workings of angular, it adds the suffix "Directive" to every directive for internal tracking for it's directive factory. 作为角度内部工作的一部分,它为每个指令添加后缀“指令”,以便为其指令工厂进行内部跟踪。 When my directive was failing, it did actually have the value "dashboardWeightTableWidgetDirective" due to this internal functionality. 当我的指令失败时,由于这个内部功能,它确实具有值“dashboardWeightTableWidgetDirective”。 Thus the report. 因此报告。 But what I had to fix was the "Widgets" part. 但我必须解决的是“小部件”部分。

  3. As an added piece of information; 作为补充信息; the file "widgets" load was failing on the variable declarations using "let". 使用“let”对变量声明文件“widgets”加载失败。 Something about the phantomjs headless browser could not deal with that instantiation. 有关phantomjs无头浏览器的东西无法处理该实例化。 Thus my code working properly in the headed browser, but not when called by phantomjs. 因此,我的代码在头部浏览器中正常工作,但在phantomjs调用时却没有。 Ultimately the problem was solved by setting all my variable instantiations back to "var". 最终,通过将所有变量实例化设置回“var”来解决问题。

I hope this saves someone from the countless hours I gave away trying to find this error. 我希望这可以节省一些人,因为我放弃了无数个小时试图找到这个错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM