【问题标题】:Problems with scoping in Nodejs moduleNodejs 模块中的范围问题
【发布时间】:2014-03-17 17:16:54
【问题描述】:

我刚从 Node 开始,却被管理“回调地狱”所困。我已经成功地使用事件发射器来从模块中触发主 js 文件中的事件,但是我无法弄清楚如何使用作用域来从模块的回调中触发事件。此外,我在模块的回调中调用原型函数时遇到问题。

具体来说,这里:

rows.forEach(function(thisRow, index, array) {
  myDb.query("SELECT COUNT(a.studentID) as total, m.fName, m.lName, m.id " +
        "from `absences` a join `members` m on a.studentID = m.id " + 
        "where a.aDate>=" + myDb.escape(thisRow['beginDate']) + " and " + 
        "a.aDate<=" + myDb.escape(thisRow['endDate']) + " and a.aDate<'" + today + "' and m.memGroup = " + myDb.escape(thisRow['orchName']) + 
        "GROUP BY a.studentID ORDER BY total DESC", function(error, row){
            if(row.length > 0) {
                retValues.push({"fullName": thisRow.fullName, "shortName": thisRow.shortName, "absences": row});
            }
            if (index === array.length - 1) {  
                //This call to this fails because, I believe, it is out of scope. 
                //How can I access this? OR how can I emit an event here that will
                //trigger the listener in the index.js?  
                this._alertServer;
                console.log(retValues);
                console.log("Done");  
            }
    });
});

完整的代码可以在以下位置找到: http://pastebin.com/Gw6kzugk

编辑 - 上面可能的答案正是您应该寻找的。以下是我最终在我的情况下所做的事情。谢谢大家!

【问题讨论】:

  • 您无法在回调中访问this。您需要使用var self = this; 在回调之外捕获它,然后使用self._alertServer();(假设_alertServer 实际上是一个函数)。

标签: javascript node.js express eventemitter


【解决方案1】:

如 cmets 中所述,您不能在回调中使用 this。您需要在回调之外捕获它,如下所示:

rows.forEach(function(thisRow, index, array) {
    var self = this; // the critical line
    myDb.query("SELECT COUNT(a.studentID) as total, m.fName, m.lName, m.id " +
        "from `absences` a join `members` m on a.studentID = m.id " + 
        "where a.aDate>=" + myDb.escape(thisRow['beginDate']) + " and " + 
        "a.aDate<=" + myDb.escape(thisRow['endDate']) + " and a.aDate<'" + today + "' and m.memGroup = " + myDb.escape(thisRow['orchName']) + 
        "GROUP BY a.studentID ORDER BY total DESC", function(error, row){
            if(row.length > 0) {
                retValues.push({"fullName": thisRow.fullName, "shortName": thisRow.shortName, "absences": row});
            }
            if (index === array.length - 1) {  
                // Use self here, not this
                self._alertServer;
                console.log(retValues);
                console.log("Done");  
            }
    });
});

【讨论】:

    【解决方案2】:

    虽然处理这种情况可能不是最优雅的方式,但我最终做的是在上下文函数中传递它,就像我在编写 Android 程序时所花费的时间一样短。

    _getAttendanceBySession = function(err, rows, retValue, context) {
        /*
        Gets attendance for each session given
        err -> Errors returned from last mySQL query
        rows -> JS Object of session list
        retValue -> string being passed to webserver
        context -> 'this'
        */
    
      var tmpHTML;
      tmpHTML = retValue;
      myDb.getConnection(function(err, conn) {
        rows.forEach(function(thisRow, index, array) {
          conn.query("SELECT COUNT(a.studentID) as total, m.fName, m.lName, m.id from `absences` a join `members` m on a.studentID = m.id where a.aDate>=" + (myDb.escape(thisRow.beginDate)) + " and a.aDate<=" + (myDb.escape(thisRow.endDate)) + " and a.aDate<'" + today + "' and m.memGroup = " + (myDb.escape(thisRow.orchName)) + " GROUP BY a.studentID ORDER BY total DESC", function(error, row) {
            if (row.length > 0) {
              tmpHTML = tmpHTML + ("<h3 class='text-center'>" + thisRow.fullName + "</h3><div class='panel-group' id='" + thisRow.shortName + "'>");
              row.forEach(function(studentRow, index2, array2) {
                var tmpLabel;
                if (studentRow.total === 1) {
                  tmpLabel = 'label-default';
                } else if (studentRow.total === 2) {
                  tmpLabel = 'label-warning';
                } else {
                  tmpLabel = 'label-danger';
                }
                tmpHTML = tmpHTML + ("<div class='panel panel-default'><div class='panel-heading'><a class='attendance-link panel-title' data-toggle='collapse' data-parent='#" + thisRow.shortName + "' href='#" + studentRow.id + "-details'><span class='label pull-left " + tmpLabel + "'>" + studentRow.total + "</span>" + studentRow.fName + " " + studentRow.lName + "</a></div><div class='panel-body collapse' id='" + studentRow.id + "-details'></div></div>");
                if (index2 === array2.length - 1) {
                  tmpHTML = tmpHTML + "</div>";
                }
              });
            }
            if (index === array.length - 1) {
              conn.release();
              context.emit("send-page", tmpHTML);
            }
          });
        });
      });
    };
    

    【讨论】:

      猜你喜欢
      • 2010-10-05
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多