NodeJS-如何使res.render()在函数之后而不是异步运行

时间:2019-09-01 21:08:41

标签: javascript node.js

我制作了一个简单的应用程序,它的UI显示了一个Input Text和两个按钮:Fetch和Show。

通常的想法是在用户键入一个单词并单击“提取”后 该应用程序将从Datamuse API请求类似“含义”的单词,并以JSON格式返回单词及其标签(名词,动词,形容词...)。

我希望如果应用程序成功获取这些单词,那么成功文本将位于名为“ fetchStatus”的变量中。

然后,我希望将“ fetchStatus”的值在res.render中转移到具有UI代码的index.ejs中,以便用户可以 查看从Datamuse进行的获取是否成功。

运行获取操作的函数称为“ FetchData(req.body.wordInput)”。

问题在于res.render函数在FetchData函数之前运行,因此fetchStatus值为空字符串。

在FetchData函数中,我尝试返回该字符串并将其传递给res.render,但没有成功。

如果将“ fetchStatus”作为参数或全局变量,也会发生同样的情况。

app.js
============
//jshint esversion:6

var fetchStatus = "";

var vocabularyTags = {
  syn: {name:"synonym", freq:0},
  n: {name:"noun", freq:0},
  v: {name:"verb", freq:0},
  adj:{name:"adjective", freq:0},
  adv:{name:"adverb", freq:0},
  u:{name:"undetermined", freq:0},
  prop: {name:"propery", freq:0}
};



const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");

var app = express();

// Setting ejs
app.set('view engine', 'ejs');

// Setting body-parser
app.use(bodyParser.urlencoded({ extended: true }));



app.get("/",function(req,res){
  // res.sendFile(__dirname+"/index.html");
  res.render("index", {fetchStatus:"", vocabularyTags:{}});


});

app.post("/",function(req,res){
  // var fetchStatus = "";
  var buttonPressed = req.body.submit;

  if (buttonPressed === "fetch") {
    FetchData(req.body.wordInput);
    console.log("Fetch Status: "+fetchStatus);
    res.render("index",{ fetchStatus:fetchStatus ,vocabularyTags:{} });
  }
  else if (buttonPressed === "show") {
    //ShowData();
    var vocabularyTagsResults = vocabularyTags;
    res.render("index",{fetchStatus:"" ,vocabularyTags:vocabularyTagsResults});

    // Clear Vocabulary Tags Frequencies
    for (var key in vocabularyTags) {
      vocabularyTags[key].freq = 0;
    }



  }

});



app.listen(3000,function(){
  console.log("Server is running on port 3000");
});


function FetchData(wordInput) {
    // var fetchStatus = "";
    var options = {
      url:"https://api.datamuse.com/words",
      method:"GET",
      qs: {
        ml: wordInput
      }
    };

    request(options,function(error,response,body){

      if (error) {
        fetchStatus = error;
      }
      else {
        var dataMuseML = JSON.parse(body);
        console.log(dataMuseML);

        // Counting the related tags
        dataMuseML.forEach(function(item){
          var tags = item.tags;
          tags.forEach(function(tag){
            vocabularyTags[tag].freq++;
          });
        });
        fetchStatus = "Fetch from Datamuse API has succeeded!";
      }
    });

    // return fetchStatus;
}


views/index.ejs
================
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <title>Datamuse API</title>
  </head>

  <body>
    <h1>Datamuse API</h1>

    <form action="/" method="post">
      <input type="text" name="wordInput" placeholder="Enter a word...">
      <button type="submit" name="submit" value="fetch">Fetch</button>
      <button type="submit" name="submit" value="show">Show</button>
    </form>

    <h3> <%= fetchStatus %> </h3>


    <% for (var key in vocabularyTags) { %>
      <p> <span><%= vocabularyTags[key].name %>:</span> <span> <%= vocabularyTags[key].freq %></span> </p>
    <% } %>


  </body>


</html>

预期结果是“ fetchStatus”将成功或出现错误文本,因此我可以将其传递给res.render,并将其放入index.ejs。

1 个答案:

答案 0 :(得分:1)

您应该为此使用Promise

function FetchData(wordInput) {
    // var fetchStatus = "";
    var options = {
      url:"https://api.datamuse.com/words",
      method:"GET",
      qs: {
        ml: wordInput
      }
    };

    return new Promise((resolve, reject) => {
        request(options,function(error,response,body){

          if (error) {
            reject(error);
          }
          else {
            var dataMuseML = JSON.parse(body);
            console.log(dataMuseML);

            // Counting the related tags
            dataMuseML.forEach(function(item){
              var tags = item.tags;
              tags.forEach(function(tag){
                vocabularyTags[tag].freq++;
              });
            });
            resolve("Fetch from Datamuse API has succeeded!");
          }
        });
      });
    // return fetchStatus;
}

然后您可以这样称呼它:

app.post("/",function(req,res){
  // var fetchStatus = "";
  var buttonPressed = req.body.submit;

  if (buttonPressed === "fetch") {
    FetchData(req.body.wordInput).then(res => {
      console.log("Fetch Status: "+res);
      res.render("index",{ fetchStatus:res ,vocabularyTags:{} });
    }).catch(err => {
      console.log("Error: "+err);
      res.render("index",{ fetchStatus:err ,vocabularyTags:{} });
    })
  }
  // ...
}

如果要使结果保持全局,则只需设置fetchStatus,然后像这样调用resolvethen

// ...
return new Promise((resolve, reject) => {
      if (error) {
        fetchStatus = error;
      }
      else {
        // ...
        fetchStatus = "Fetch from Datamuse API has succeeded!";
      }
    });
  });
  resolve(fetchStatus);
}

app.post("/",function(req,res){
  if (buttonPressed === "fetch") {
    FetchData(req.body.wordInput).then(res => {
      // res or fetchStatus should be available here but it's better to use res
      console.log("Fetch Status: "+res);
      res.render("index",{ fetchStatus:res ,vocabularyTags:{} });
    })
  }
}
相关问题