node.js 服务器响应中异步函数调用的结果

node.js result from asynchronous function call in server response

对不起,这肯定已经回答过了。我特别了解这里的这个线程:

How do I return the response from an asynchronous call?

但老实说,我还是迷路了。我根本不明白如何异步调用函数并将此函数的 return 包含在对客户端的响应中。

我有一个相当简单的路由(在 routes.js 中),它将向网页提供内容。该站点的一个特定元素是 rfid 标签列表。此列表由一个函数填充,我当然喜欢并且必须调用异步函数。

我使用 pug(以前称为 jade)作为模板渲染引擎,我的 tags.pug 看起来像这样:

extends index.pug
block content 
  h2!= subheadline
  p!= messagetext
  p!= bodyContent

看到最后一个 p!=bodyContent 了吗?此元素应为标签列表。

下面是来自我的 routes.js 的代码片段,带有 app.get('/tags'),其中该站点应 returned:

// get the listing of all stored rfid tags
app.get("/tags", function(req, res) {
  res.render('tags', {
     title: 'RFID Tag Startseite',
     headline: 'RFID Tag Startseite',
     subheadline: 'Verfügbare Tags',
     messagetext: 'Bitte ein RFID Tag auswählen, um mehr Daten angezeigt zu bekommen',
     bodyContent: tagController.getTagList(app, function(tagController))
  });
})

现在,如您所见,我正在尝试从另一个模块 (tagController) 的 bodyContent 位置调用函数 (getTagList),这将提供标签列表。

下面你可以看到我的getTagList()函数的代码:

var getTagList = function(app, result){
  // get global app variables
  var DEBUG = app.get('DEBUG');
  var svrAddr = app.get('svrAddr');
  var rfidTagDir = app.get('rfidTagDir');

  var responseContent = '';

    fs.readdir(rfidTagDir, function(err, items) {
      responseContent = "{\'response\': \'info\', \'message\': \'list of all stored rfid tags\', \'tags\': ["

        for (i in items) {
          var tag = items[i].toString().substring(0,items[i].indexOf('.'));
            responseContent += "{\'tag\': \'" + tag + "\', \'endpoint\': \'"+svrAddr+"/tags/tag/" + tag + "\', \'file\': \'"+items[i]+"\'}"
            if (i<items.length-1) responseContent += ",";
        }
        responseContent += "]}"
      if (DEBUG) console.log(responseContent);
      result = responseContent;
      return result;
  )};

我的问题是,它不起作用。上面的代码给出了错误:

 SyntaxError: Unexpected token )

两个中的最后一个)。如果我尝试在 res.send 之前填充变量(比如 tagContent 或其他)并将该变量包含在响应中,我根本看不到函数调用的结果。然而,在 console.log 中,我可以看到正在执行的函数和生成的标签列表。

谁能告诉我,如何从我的 routes.js 中的模块 tagController 调用我的函数 getTagList 以便显示内容???

亲切的问候,

基督教徒

所以问题是 getTagList 将执行一个异步操作,无论你想做什么 return 它不能保证它是正确的......所以为了能够处理这个你通过getTagList 的回调函数,将在异步 fs.readdir 的回调函数内部调用,这是您 100% 确定预期结果正确的地方。

下面是更新后的 getTagList 函数

var getTagList = function(app, callback) {
    // get global app variables
    var DEBUG = app.get('DEBUG');
    var svrAddr = app.get('svrAddr');
    var rfidTagDir = app.get('rfidTagDir');

    var responseContent = '';
    fs.readdir(rfidTagDir, function(err, items) {
            if (err) {
                callback(err);
            } else {
                responseContent = "{\'response\': \'info\', \'message\': \'list of all stored rfid tags\', \'tags\': ["

                for (i in items) {
                    var tag = items[i].toString().substring(0, items[i].indexOf('.'));
                    responseContent += "{\'tag\': \'" + tag + "\', \'endpoint\': \'" + svrAddr + "/tags/tag/" + tag + "\', \'file\': \'" + items[i] + "\'}"
                    if (i < items.length - 1) responseContent += ",";
                }

                responseContent += "]}"
                if (DEBUG) {
                    console.log(responseContent);
                }
                //Here we are 100% sure we have the correct expected result so we call the callback function with correct data `responseContent`
                callback(null, responseContent);
            }
        )
    };
}

您还更新路由以仅在 getTagList 的回调函数内的数据可用时发送请求,检查下面的代码

app.get("/tags", function(req, res) {
    tagController.getTagList(app, function(err, result) {
        if (err) {
            console.log(err);
            //Handle error response
        } else {
            res.render('tags', {
                title: 'RFID Tag Startseite',
                headline: 'RFID Tag Startseite',
                subheadline: 'Verf&uuml;gbare Tags',
                messagetext: 'Bitte ein RFID Tag ausw&auml;hlen, um mehr Daten angezeigt zu bekommen',
                bodyContent: result
            });
        }
    });
})

您还可以注意到回调函数是如何在节点中实现的...我们将任何错误传递给第一个参数,并将结果传递给第二个参数..以获得更好的可维护代码。

最后,您可以看到代码中已经存在的 fs.readdir 实际上使用了相同的概念,您会看到您正在使用回调函数来正确访问项目。