在 vue 3 中获取停止后端并且在一次正常工作后什么都不做
Fetch in vue 3 stops backend and does nothing after working fine one time
所以,我的问题是当我尝试登录我的 vue 应用程序时,当我尝试从它获取对象数组时,后端会自动停止。
更具体一点。
这是我从数据库中获取对象的“尝试”。
let url = utils.url;
let requestParam = utils.globalRequestParameters;
requestParam.method = "GET";
requestParam.body = null;
if (cars.value.length == 0) {
fetch(url + "cars", requestParam).then((res) =>
res.json().then(async (res) => {
store.dispatch("Car/fetchCars", res);
fetch(url + "users", requestParam).then((users) =>
users.json().then((users) => {
for (let car of res) {
let userCar = Object.values(users).find(
(a) => a.id == car.userId
);
car.userName = userCar.lastName + " " + userCar.firstName;
}
})
);
})
);
}
And login in view Login.vue
let requestParameters = utils.globalRequestParameters;
requestParameters.method = "POST";
requestParameters.body = JSON.stringify(data);
fetch(utils.url + "login", requestParameters).then((res) => {
res.json().then((res) => {
this.mesaj = res.message;
console.log("token:" + res.token);
if (res.token) {
localStorage.setItem("token", res.token);
console.log("token:" + res.token);
console.log("id:" + res.id);
let id = res.id;
requestParameters.method = "GET";
requestParameters.body = null;
this.$store.dispatch("login", true);
fetch(utils.url + "users/" + id, requestParameters).then(
(res) => {
res.json().then((res) => {
console.log("Jos de tot");
this.$store.dispatch("User/setUser", res);
console.log(this.$store.state.User.user);
this.$router.push("/");
});
}
);
}
});
});
}
},
注意。
cars 是 return store.state.cars 的计算值
实用程序是
let url = "http://127.0.0.1:3000/";
let globalRequestParameters = {
method: "GET",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
referrerPolicy: "no-referrer",
};
module.exports.globalRequestParameters = globalRequestParameters;
module.exports.url = url;
此处在第一次获取时后端停止,并且未完成获取。
后端路由是
router.get('/cars', async (req, res) => {
res.json(await functions.getAllCars(req,res));
})
getAllCars = async (req, res) => {
const snapshot = await db.collection("Cars").get();
let cars = [];
snapshot.forEach((doc) => {
let car = {
id: doc.id,
userId: doc.data().userId,
manufacturer: doc.data().manufacturer,
model: doc.data().model,
color: doc.data().color,
plate: doc.data().plate,
price: doc.data().price,
description: doc.data().description
};
cars.push(car);
});
res.status(200).send(cars);
return
};
router.get("/users/:id", async (req, res) => {
res.json(await functions.getUserById(req.params.id, res));
});
getUserById = (id, res) => {
db
.collection("Users")
.doc(id)
.get()
.then((response) => {
let user = {};
user.id = response.id;
user.firstName = response.data().firstName;
user.lastName = response.data().lastName;
user.gender = response.data().gender;
user.jobTitle = response.data().jobTitle;
user.phone = response.data().phone;
user.email = response.data().email;
user.isAdmin = response.data().isAdmin;
res.status(200).send(user);
return
})
.catch((err) => {
res.status(404).send({ message: "User not found" });
return
});
};
用户被正确检索,我通过控制台日志在控制台中看到它,但我在终端和控制台中得到的消息是:
*作为最后的说明。我使用 vue 3,node.js 版本 16.13.0 和 Firestore 作为数据库。昨天在我的另一台电脑上一切正常,但我不得不去某个地方使用我的笔记本电脑。也许我的笔记本电脑有问题。我所做的只是安装正面和背面的模块
我认为这与 Vue 无关 - 这只是您的 Express 后端代码的问题
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
如所述here:
That particular error occurs whenever you try to send more than one response to the same request and is usually caused by improper asynchronous code.
getAllCars
getAllCars
是内部带有 await
的异步函数 - 一旦这个 await
被命中(连同 db.collection("Cars").get()
调用),函数 returns在 res.json(await functions.getAllCars(req,res));
等待的承诺
当数据库调用完成时,将执行该方法的其余部分,包括 res.status(200).send(cars)
- 这会将 cars
数组发送到客户端和 returns undefined
(这就是简单的 return
所做的)并且执行 res.json(undefined)
导致上面的错误(您正在尝试发送第二个响应)
getUserById
你说这个处理程序工作正常,但我真的很怀疑 - 据我所知,这也不应该工作
您正在用 res.json(await functions.getUserById(req.params.id, res));
调用它。要 await
实际做某事,等待的函数必须 return 一个 Promise(通过在内部使用 await
隐式或显式)或一般 "thenable" object。 getUserById
函数 return 什么都没有(then()
或 catch()
中的 return
语句不算数!...这些是不同的函数)
这个问题可以通过 return db.collection("Users").doc(id).get().then()
来解决,但是你会得到与 getAllCars
情况相同的错误
正确的模式
- 不要同时使用
res.status(200).send()
和 res.json()
- 为了理智起见(至少在你真正知道自己在做什么之前)不要将承诺与
async
/await
混在一起
async
函数应该 return 数据(不要在没有“参数”的情况下使用 return
)
以下代码显示了基于 Promise 和 async
/await
风格(从某种意义上说,它是“伪代码”,我没有测试过它,但希望你能理解)
router.get('/cars', async (req, res) => {
try {
const response = await functions.getAllCars()
res.status(200).json(response);
} catch() {
res.sendStatus(500)
}
})
getAllCars = async () => {
const snapshot = await db.collection("Cars").get();
let cars = [];
snapshot.forEach((doc) => {
let car = {
id: doc.id,
userId: doc.data().userId,
manufacturer: doc.data().manufacturer,
model: doc.data().model,
color: doc.data().color,
plate: doc.data().plate,
price: doc.data().price,
description: doc.data().description
};
cars.push(car);
});
// res.status(200).send(cars); //* should be handled by caller
return cars //* return the data
};
router.get("/users/:id", async (req, res) => {
functions.getUserById(req.params.id)
.then((response) => {
if(response === null)
res.status(404).json({ message: "User not found" });
else
res.status(200).json(response);
})
.catch(er) {
res.status(500).send(er.message)
}
});
getUserById = (id) => {
return db //* return the promise
.collection("Users")
.doc(id)
.get()
.then((response) => {
let user = {};
user.id = response.id;
user.firstName = response.data().firstName;
user.lastName = response.data().lastName;
user.gender = response.data().gender;
user.jobTitle = response.data().jobTitle;
user.phone = response.data().phone;
user.email = response.data().email;
user.isAdmin = response.data().isAdmin;
// res.status(200).send(user); //* should be handled by caller
return user //* return the data
})
.catch((err) => {
return null
});
};
所以,我的问题是当我尝试登录我的 vue 应用程序时,当我尝试从它获取对象数组时,后端会自动停止。
更具体一点。 这是我从数据库中获取对象的“尝试”。
let url = utils.url;
let requestParam = utils.globalRequestParameters;
requestParam.method = "GET";
requestParam.body = null;
if (cars.value.length == 0) {
fetch(url + "cars", requestParam).then((res) =>
res.json().then(async (res) => {
store.dispatch("Car/fetchCars", res);
fetch(url + "users", requestParam).then((users) =>
users.json().then((users) => {
for (let car of res) {
let userCar = Object.values(users).find(
(a) => a.id == car.userId
);
car.userName = userCar.lastName + " " + userCar.firstName;
}
})
);
})
);
}
And login in view Login.vue
let requestParameters = utils.globalRequestParameters;
requestParameters.method = "POST";
requestParameters.body = JSON.stringify(data);
fetch(utils.url + "login", requestParameters).then((res) => {
res.json().then((res) => {
this.mesaj = res.message;
console.log("token:" + res.token);
if (res.token) {
localStorage.setItem("token", res.token);
console.log("token:" + res.token);
console.log("id:" + res.id);
let id = res.id;
requestParameters.method = "GET";
requestParameters.body = null;
this.$store.dispatch("login", true);
fetch(utils.url + "users/" + id, requestParameters).then(
(res) => {
res.json().then((res) => {
console.log("Jos de tot");
this.$store.dispatch("User/setUser", res);
console.log(this.$store.state.User.user);
this.$router.push("/");
});
}
);
}
});
});
}
},
注意。 cars 是 return store.state.cars 的计算值 实用程序是
let url = "http://127.0.0.1:3000/";
let globalRequestParameters = {
method: "GET",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
referrerPolicy: "no-referrer",
};
module.exports.globalRequestParameters = globalRequestParameters;
module.exports.url = url;
此处在第一次获取时后端停止,并且未完成获取。
后端路由是
router.get('/cars', async (req, res) => {
res.json(await functions.getAllCars(req,res));
})
getAllCars = async (req, res) => {
const snapshot = await db.collection("Cars").get();
let cars = [];
snapshot.forEach((doc) => {
let car = {
id: doc.id,
userId: doc.data().userId,
manufacturer: doc.data().manufacturer,
model: doc.data().model,
color: doc.data().color,
plate: doc.data().plate,
price: doc.data().price,
description: doc.data().description
};
cars.push(car);
});
res.status(200).send(cars);
return
};
router.get("/users/:id", async (req, res) => {
res.json(await functions.getUserById(req.params.id, res));
});
getUserById = (id, res) => {
db
.collection("Users")
.doc(id)
.get()
.then((response) => {
let user = {};
user.id = response.id;
user.firstName = response.data().firstName;
user.lastName = response.data().lastName;
user.gender = response.data().gender;
user.jobTitle = response.data().jobTitle;
user.phone = response.data().phone;
user.email = response.data().email;
user.isAdmin = response.data().isAdmin;
res.status(200).send(user);
return
})
.catch((err) => {
res.status(404).send({ message: "User not found" });
return
});
};
用户被正确检索,我通过控制台日志在控制台中看到它,但我在终端和控制台中得到的消息是:
*作为最后的说明。我使用 vue 3,node.js 版本 16.13.0 和 Firestore 作为数据库。昨天在我的另一台电脑上一切正常,但我不得不去某个地方使用我的笔记本电脑。也许我的笔记本电脑有问题。我所做的只是安装正面和背面的模块
我认为这与 Vue 无关 - 这只是您的 Express 后端代码的问题
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
如所述here:
That particular error occurs whenever you try to send more than one response to the same request and is usually caused by improper asynchronous code.
getAllCars
getAllCars
是内部带有 await
的异步函数 - 一旦这个 await
被命中(连同 db.collection("Cars").get()
调用),函数 returns在 res.json(await functions.getAllCars(req,res));
当数据库调用完成时,将执行该方法的其余部分,包括 res.status(200).send(cars)
- 这会将 cars
数组发送到客户端和 returns undefined
(这就是简单的 return
所做的)并且执行 res.json(undefined)
导致上面的错误(您正在尝试发送第二个响应)
getUserById
你说这个处理程序工作正常,但我真的很怀疑 - 据我所知,这也不应该工作
您正在用 res.json(await functions.getUserById(req.params.id, res));
调用它。要 await
实际做某事,等待的函数必须 return 一个 Promise(通过在内部使用 await
隐式或显式)或一般 "thenable" object。 getUserById
函数 return 什么都没有(then()
或 catch()
中的 return
语句不算数!...这些是不同的函数)
这个问题可以通过 return db.collection("Users").doc(id).get().then()
来解决,但是你会得到与 getAllCars
情况相同的错误
正确的模式
- 不要同时使用
res.status(200).send()
和res.json()
- 为了理智起见(至少在你真正知道自己在做什么之前)不要将承诺与
async
/await
混在一起
async
函数应该 return 数据(不要在没有“参数”的情况下使用return
)
以下代码显示了基于 Promise 和 async
/await
风格(从某种意义上说,它是“伪代码”,我没有测试过它,但希望你能理解)
router.get('/cars', async (req, res) => {
try {
const response = await functions.getAllCars()
res.status(200).json(response);
} catch() {
res.sendStatus(500)
}
})
getAllCars = async () => {
const snapshot = await db.collection("Cars").get();
let cars = [];
snapshot.forEach((doc) => {
let car = {
id: doc.id,
userId: doc.data().userId,
manufacturer: doc.data().manufacturer,
model: doc.data().model,
color: doc.data().color,
plate: doc.data().plate,
price: doc.data().price,
description: doc.data().description
};
cars.push(car);
});
// res.status(200).send(cars); //* should be handled by caller
return cars //* return the data
};
router.get("/users/:id", async (req, res) => {
functions.getUserById(req.params.id)
.then((response) => {
if(response === null)
res.status(404).json({ message: "User not found" });
else
res.status(200).json(response);
})
.catch(er) {
res.status(500).send(er.message)
}
});
getUserById = (id) => {
return db //* return the promise
.collection("Users")
.doc(id)
.get()
.then((response) => {
let user = {};
user.id = response.id;
user.firstName = response.data().firstName;
user.lastName = response.data().lastName;
user.gender = response.data().gender;
user.jobTitle = response.data().jobTitle;
user.phone = response.data().phone;
user.email = response.data().email;
user.isAdmin = response.data().isAdmin;
// res.status(200).send(user); //* should be handled by caller
return user //* return the data
})
.catch((err) => {
return null
});
};