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

Posted

技术标签:

【中文标题】AngularJS,Node.js,节点模块“幻影”... 注入错误,angularjs 试图加载我的指令 + 后缀【英文标题】:AngularJS, Node.js, node module 'phantom'... Injection error, angularjs trying to load my directive + Suffix 【发布时间】:2018-09-20 15:39:32 【问题描述】:

当我加载一个 AngularJS 页面时,它加载得很好。没有控制台错误。内容按预期显示。

当我从另一个应用程序加载相同的页面时,使用 Node 模块 'phantom' 失败并出现错误:

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

从 Angular 网站,此链接等同于:Unknown provider: WidgetsProvider <- Widgets <- dashboardWeightTableWidgetDirective

请注意指令名称。 “dashboardWeightTableWidgetDirective”。该指令被命名,并在我的代码中到处被称为:“dashboardWeightTableWidget”。

发生的事情是它在 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 = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;

然后尝试使用更改后的名称来执行看起来像依赖注入的操作。但这是一个指令。定义如下所示。

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

同样,这只发生在我尝试通过幻像渲染页面时,使用此命令附带的节点模块:npm install phantom

我的相关幻像代码如下所示:

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();
              )

...

还有一条评论:我不知道如何在幻像渲染调用期间进入加载页面客户端代码。如果我能做到这一点,那么我可以单步执行代码,并可能查看渲染过程中出现的问题。如果有人知道这一点,我也将不胜感激。你知道,“授人以渔”。

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);
      );
  );

【问题讨论】:

您可能遇到了时间问题。看看你的承诺链。您从 setTimeout 返回,但该值被丢弃。您需要返回一个承诺并在回调中解决它 Aluan Haddad... 使用我添加到问题中的代码:立即弹出奇怪的指令错误。然后,20 秒后,我的控制台打印出来,一个 empty_web_page.png 到达。这表明错误发生在 page.open 调用中。您是否仍然怀疑承诺链、时间问题? 这是一种明显的可能性。不管 return 语句的存在表明了一个错误,一种或另一种方式。它并没有像它认为的那样做。 .then(() => new Promise(resolve => setTimeout(resolve);)).then(()=> _page.render(conf.options.filePath).then(() => page.close();) 我还意识到其他事情:您的外部承诺构造函数调用已损坏。你既没有解决也没有拒绝它,return 是一个错误。 【参考方案1】:

自我回答:

最终我遇到了文件包含问题。在这一点上这真的无关紧要。不过,我确实认为有 3 点值得从我的旅程中吸取。

Unknown provider: WidgetsProvider <- Widgets <- dashboardWeightTableWidgetDirective

    我认为这个错误是在告诉我仪表板WeightTableWidgetDirective 有问题。角度是发生错误的地方。但是这个错误实际上告诉我的是我在dashboardWeightTableWidget指令中有一个错误,错误是它找不到提供程序“Widgets”。因此,实际问题是提供“小部件”的文件中的错误。

    作为 Angular 内部工作的一部分,它为每个指令添加后缀“指令”,以便对其指令工厂进行内部跟踪。当我的指令失败时,由于此内部功能,它实际上确实具有值“dashboardWeightTableWidgetDirective”。因此报告。但我必须修复的是“小部件”部分。

    作为附加信息;文件“widgets”加载在使用“let”的变量声明上失败。 phantomjs 无头浏览器无法处理该实例化。因此,我的代码在带头浏览器中正常工作,但在被 phantomjs 调用时不能正常工作。最终,通过将我所有的变量实例设置回“var”来解决问题。

我希望这可以帮助我避免花费无数个小时来寻找这个错误。

【讨论】:

以上是关于AngularJS,Node.js,节点模块“幻影”... 注入错误,angularjs 试图加载我的指令 + 后缀的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 使用angularjs取得Nodejs http服务端返回的JSON数组示例

如何在 AngularJS 的索引页面上使用来自 Node.js 的信息

Node.js + AngularJS + Socket.io:推送的数据在控制器中不可用

Node.js:如何创建付费节点模块?

如何将 node.js 模块导入 node.js 模块

AngularJS 拦截器没有将 JWT Bearer 放入 node.js 应用程序的每个请求中