还有其他与此相关的问题,但没有一个是特定于此问题的。
我找不到任何东西。他们都没有问以下问题:
";为什么我的服务器端node-fatch API在node Express中工作,但它在客户端立即崩溃,返回以下错误消息:;未捕获引用错误:正文未定义">
我非常相信服务器端API会返回正确的响应。
我试着把身体放在头部,两者都是"身体";身体:身体;并且作为";body:JSON.stringfy(body).
我还尝试将API响应字符串化。没有骰子。
在下面的服务器端屏幕截图中,Chrome浏览器中的开发人员工具指示向NASA服务器发出成功请求。在"网络"下,有效载荷是正确的。响应也是正确的,图库由用户选择的火星车图像URL填充。
然而,在客户端屏幕截图中,它返回一个";引用错误:主体未定义";,不管我尝试什么。如图所示,该消息变为";无效的漫游者名称";来自美国国家航空航天局的错误,画廊突然没有图像URL。
在命令提示符中,我看到了类似的结果。
漫游者在服务器端的定义正确http://localhost:3000/userinput,在我选择漫游者并单击提交之后。当我回到http://localhost:3000/,在命令提示符中记录的相同漫游者名称突然变为";未定义">
我看不出我做错了什么。
我怀疑问题在于服务器端API的这两行代码。
.then(response => response.json()) // send json to client
.then(gallery => response.send({gallery})) // send gallery to browser (so I can see it)
正如我所理解的,1)第一个将json响应返回到客户端,2)第二个将响应作为文本发送到浏览器。
很明显,我在浏览器中看到的并不是客户端获取API接收到的内容,但我不知道当NASA服务器返回正确的响应时会是什么情况。我看到正确的图像URL返回并发送到浏览器/用户输入">
我理解服务器和客户端Node Expres之间的区别,或者我认为我理解。但我不明白我在这里做错了什么。如果是异步问题,我看不出来
有人能解释一下这个问题吗
谢谢你复习我的问题。
请注意:我收到Stack Overflow的消息,说我还不允许在问题中嵌入图像。
但它包含了这些图片的链接。
我写这个问题的时候就知道了。
HTML表单中的相关代码:
<form action="http://localhost:3000/userinput" method="POST">
<button id="submit" name="submit">Send Images</button>
相关服务器端API代码:
app.use('/', express.static(path.join(__dirname, '../public')));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors("*"));
app.post('/userinput', async (request, response) => {
const rover = request.body.rover
console.log("SERVER SIDE ROVER: ", rover)
try {
const gallery = await fetch(`https://api.nasa.gov/mars-photos/api/v1/rovers/${rover}/latest_photos?api_key=DH46IQlx0gMyXPmLAgkxXDSPo2OrbIjPs8OJLj6L`)
.then(response => response.json()) // send json to client
.then(gallery => response.send({gallery})) // send gallery to browser (so I can see it)
} catch (err) {
console.log(`RESPONSE STATUs: ${response.status}`, err);
}
return response.json();
});
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port${port}`);
相关客户端API代码:
// Single async higher-order/callback function
// Retrieves image data and update store/new state
// getRoverPhotos is Higher Order function.
// RoverPhotos as callback function.
const getRoverPhotos = async (state, fn) => {
const response = await fetch("http://localhost:3000/userinput", {
method: "POST",
headers: {'Content-Type': 'application/JSON' }
})
console.log("RESPONSE CLIENT: ", response)
const jsonImageData = await response.json()
console.log("JSON Image Data")
console.log(jsonImageData)
const ImageData = await jsonImageData.gallery.latest_photos.map(photo => {
return photo.img_src;
});
const newState = jsonImageData.gallery
updateStore(store, newState)
return ImageData
}
getRoverPhotos(store, updateStore)
服务器端屏幕截图
在浏览器中显示NASA的响应,并在开发者工具中成功返回图像URL库=>网络=>响应
客户端屏幕截图
显示失败的响应。"开发人员工具"下的库已清空=>控制台
我会回答我的问题,因为有几个问题。
在大多数情况下,我忘记了一个步骤,即在将请求发送到服务器端api之前,在客户端为服务器端准备请求。
这一切的准备、发送和接收都在一个函数(getRoverPhotos())中进行,服务器api作为NASA服务器的中介。
身体没有定义,因为我的头脑陷入了细节中,不知道如何最好地构建请求。最后,我直接将请求发送到服务器端,而没有将主体准备为JSON字符串/对象。
它看起来也很有效,因为我在";localhost:3000/userinput";地址,但当我返回到客户端并重置请求时,它就掉了。我认为服务器端app.post中的两行是罪魁祸首,这是正确的。NASA将正确的结果发送到服务器端地址的浏览器,但没有以正确的格式返回到客户端。因此;未定义的主体";错误,尽管我可以在服务器端的浏览器中看到它。
我希望这样做。这对我来说很有意义……现在。
感谢昆汀在评论中为我指明了这条路。
这是我表格中的相关代码。
<form name="form" id="form" method="POST" action="/results"></form>
<input id="submit" name='submit' type="button" value="Transmit Images" onclick="getRoverPhotos(store,updateStore)" />
关于表格有两个要点:
- 表单操作属性包含新的服务器端API地址
- onclick-button属性调用将请求发送到该地址的函数
以下是客户端的相关代码
按钮事件将用户输入提交给客户端函数getRoverPhotos(),后者将其转换为JavaScript对象,删除它,然后发送它以从服务器端api获取数据。
回复包括用户选择的火星车的最新照片,这些照片最终会显示在带有相关信息的图库中(例如拍摄日期)。
const getRoverPhotos = async (store, fn) => {
const name = document.getElementById('name').value;
const rover = document.getElementById('rover').value;
const camera = document.getElementById('camera').value;
const userInfo = new Object();
userInfo.name = name
userInfo.rover = rover
userInfo.camera = camera
const body = JSON.stringify(userInfo)
const options = {
method: "POST",
headers: {'Content-Type': "application/json"},
body: body
};
const response = await fetch('/results', options)
console.log("Okay? ", response.ok)
const json = await response.json();
console.log(json)
if (response.ok === true) {
const newState = json
updateStore(store, newState)
console.log("Response OK. New Store: ", store)
return store
} else {
throw new Error()
}};
这是来自服务器端的相关代码
两个";那么";台词是我上面提到的罪魁祸首。一种方法是在服务器端地址将数据以文本形式返回到浏览器。但另一个是未能将数据返回给客户端。
try {
const gallery = await fetch(`https://api.nasa.gov/mars-photos/api/v1/rovers/${rover}/latest_photos?api_key=DH46IQlx0gMyXPmLAgkxXDSPo2OrbIjPs8OJLj6L`)
**.then(response => response.json()) // send json back to client
.then(gallery => response.send({gallery})) // send gallery to browser (so I can see it)**
} catch (err) {
console.log(`RESPONSE STATUS: ${response.status}`, err);
}
console.log("GALLERY:")
console.log(response.json())
return response.json()
});
一旦收到请求,服务器端的app.post/results-api就会根据用户选择的漫游者从NASA的服务器中获取数据。
app.post/results-api函数然后将数据返回给客户端上的getRoverPhotos函数作为JSON,用于更新回调函数updateStore()中的主内存对象(称为store)。
就是这样,而且很管用!