Javascript NodeJS-如何使res.render()在函数之后而不是异步运行
我制作了一个简单的应用程序,它的UI显示一个输入文本和两个按钮:Fetch和Show 一般的想法是在用户键入一个单词并单击“Fetch”之后 该应用程序将从DatamuseAPI请求类似于单词的含义,并以JSON格式返回单词及其标记(名词、动词、形容词…) 我希望,如果应用程序成功获取这些单词,那么成功文本将位于名为“fetchStatus”的变量中 之后,我希望“fetchStatus”的值将在res.render中传输到具有UI代码的index.ejs,以便用户能够 查看从Datamuse获取是否成功 运行fetch的函数称为“FetchData(req.body.wordInput)” 问题是res.render函数在FetchData函数之前运行,因此fetchStatus值是空字符串 在函数FetchData中,我尝试返回字符串并将其传递给res.render,但没有成功 如果将“fetchStatus”作为参数或全局变量,也会出现同样的情况Javascript NodeJS-如何使res.render()在函数之后而不是异步运行,javascript,node.js,Javascript,Node.js,我制作了一个简单的应用程序,它的UI显示一个输入文本和两个按钮:Fetch和Show 一般的想法是在用户键入一个单词并单击“Fetch”之后 该应用程序将从DatamuseAPI请求类似于单词的含义,并以JSON格式返回单词及其标记(名词、动词、形容词…) 我希望,如果应用程序成功获取这些单词,那么成功文本将位于名为“fetchStatus”的变量中 之后,我希望“fetchStatus”的值将在res.render中传输到具有UI代码的index.ejs,以便用户能够 查看从Datamuse获
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>
app.js
============
//jshint版本:6
var fetchStatus=“”;
var词汇标签={
syn:{name:“同义词”,频率:0},
n:{name:“名词”,频率:0},
v:{name:“动词”,频率:0},
形容词:{name:“形容词”,频率:0},
副词:{name:“副词”,频率:0},
u:{name:“待定”,频率:0},
道具:{name:“propery”,频率:0}
};
const express=要求(“express”);
const bodyParser=require(“body parser”);
常量请求=要求(“请求”);
var-app=express();
//设置ejs
应用程序集(“查看引擎”、“ejs”);
//设置主体解析器
use(bodyParser.urlencoded({extended:true}));
应用程序获取(“/”,函数(请求,恢复){
//res.sendFile(uu dirname+“/index.html”);
res.render(“索引”,{fetchStatus:,词汇标记:{});
});
应用程序post(“/”,功能(请求,回复){
//var fetchStatus=“”;
var buttonPressed=req.body.submit;
如果(按下按钮==“获取”){
获取数据(请求主体wordInput);
日志(“获取状态:+fetchStatus”);
res.render(“索引”{fetchStatus:fetchStatus,词汇标记:{}});
}
否则如果(按下按钮==“显示”){
//ShowData();
var vocabularyTagsResults=vocabularyTags;
res.render(“index”,{fetchStatus:,vocabularyTags:vocabularyTagsResults});
//清除词汇标签和频率
for(词汇标签中的var键){
词汇标签[key].freq=0;
}
}
});
app.listen(3000,函数(){
log(“服务器正在端口3000上运行”);
});
函数FetchData(wordInput){
//var fetchStatus=“”;
变量选项={
url:“https://api.datamuse.com/words",
方法:“获取”,
qs:{
ml:wordInput
}
};
请求(选项、功能(错误、响应、正文){
如果(错误){
fetchStatus=错误;
}
否则{
var dataMuseML=JSON.parse(body);
console.log(dataMuseML);
//计算相关标签
dataMuseML.forEach(函数(项){
var tags=item.tags;
tags.forEach(函数(tag){
词汇标签[tag].freq++;
});
});
fetchStatus=“从Datamuse API获取已成功!”;
}
});
//返回状态;
}
视图/index.ejs
================
DatamuseAPI
DatamuseAPI
取来
显示
:
预期结果是“fetchStatus”将有一个成功或错误文本,因此我可以将其传递给res.render,res.render将其放入index.ejs中。为此,您应该使用
Promise
函数获取数据(wordInput){
//var fetchStatus=“”;
变量选项={
url:“https://api.datamuse.com/words",
方法:“获取”,
qs:{
ml:wordInput
}
};
返回新承诺((解决、拒绝)=>{
请求(选项、功能(错误、响应、正文){
如果(错误){
拒绝(错误);
}
否则{
var dataMuseML=JSON.parse(body);
console.log(dataMuseML);
//计算相关标签
dataMuseML.forEach(函数(项){
var tags=item.tags;
tags.forEach(函数(tag){
词汇标签[tag].freq++;
});
});
解析(“从Datamuse API获取已成功!”);
}
});
});
//返回状态;
}
然后你可以这样称呼它:
app.post(“/”,函数(req,res){
//var fetchStatus=“”;
var buttonPressed=req.body.submit;
如果(按下按钮==“获取”){
获取数据(req.body.wordInput)。然后(res=>{
日志(“获取状态:+res”);
res.render(“索引”{fetchStatus:res,词汇标记:{}});
}).catch(错误=>{
日志(“错误:+err”);
res.render(“index”,{fetchStatus:err,词汇标签:{}});
})
}
// ...
}
如果要将结果保存在全局中,只需设置fetchStatus,然后调用resolve
和,然后像这样调用:
/。。。
返回新承诺((解决、拒绝)=>{
如果(错误){
fetchStatus=错误;
}
否则{
// ...
fetchStatus=“从Datamuse API获取已成功!”;
}
});
});
解决(获取状态);
}
应用程序post(“/”,功能(请求,回复){
如果(按下按钮==“获取”){
获取数据(req.body.wordInput)。然后(res=>{
//res或fetchStatus应该在这里可用,但最好使用res
日志(“获取状态:+res”);
res.render(“索引”{fetchStatus:res,词汇标记:{}});
})
}
}
非常感谢Mckael的可能副本。我真的很感激它,它工作得很好。根据您的解决方案,我将“then”中的“res”更改为:FetchData(req.body.wordInput)。然后(fetchStatus=>{console.log(“fetchStatus:+fetchStatus”);res。