我正在尝试制作一个社交媒体类型的应用程序,目前正在尝试实现搜索功能以便能够找到朋友。我有下面的代码,它有时工作,有时不工作(真的令人沮丧!)我很确定这与 javascript 的异步性质有关。我想我可以通过将第二个查找放在 then 函数中来解决这个问题。代码应该搜索以检查用户的名字,然后搜索用户的姓氏并将其推送到名为 users 的数组中,然后将其展平并编辑为仅具有唯一的用户对象。然后将其传递到显示用户的把手。问题似乎出现在以下测试中,这些测试处理多个单词,有时会搜索第二个单词,有时不会:
const User = require("../models/user");
const SearchController = {
Index: (req, res) => {
const users = [];
User.find().then((user) => {
users.push(user);
const merged = [].concat.apply([], users);
const uniqueArray = merged.filter((value, index) => {
const _value = JSON.stringify(value);
return (
index ===
merged.findIndex((obj) => {
return JSON.stringify(obj) === _value;
})
);
});
res.render("search/index", { users: uniqueArray });
});
},
Create: (req, res) => {
const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);
const users = [];
searchArray.forEach((name) => {
User.find({
firstName: { $regex: name, $options: "i" },
// lastName: { $regex: name, $options: "i" },
}).then((user) => {
users.push(user);
User.find({
// firstName: { $regex: name, $options: "i" },
lastName: { $regex: name, $options: "i" },
}).then((user) => {
users.push(user);
const merged = [].concat.apply([], users);
const uniqueArray = merged.filter((value, index) => {
const _value = JSON.stringify(value);
return (
index ===
merged.findIndex((obj) => {
return JSON.stringify(obj) === _value;
})
);
});
res.render("search/index", { users: uniqueArray });
});
});
});
},
};
module.exports = SearchController;
describe("Searching users", () => {
beforeEach(() => {
cy.signUp();
cy.signUp("Chris", "Coding", "[email protected]", "12345");
cy.signUp("Paul", "Coding", "[email protected]", "12345");
cy.signUp("Adam", "Woodcock", "[email protected]", "12345");
cy.signUp("Kathleen", "Woodcock", "[email protected]", "12345");
cy.signUp("George", "Hett", "[email protected]", "12345");
cy.signUp("Rob", "Oman", "[email protected]", "12345");
});
it("A user can search for other users", () => {
cy.login();
cy.get("#searchBox").type("george");
cy.get("#searchButton").click();
cy.get(".user-container").first().should("contain", "George Hett");
});
it("A user can search for other users by last name", () => {
cy.login();
cy.get("#searchBox").type("woodcock");
cy.get("#searchButton").click();
cy.get(".user-container").should("have.length", 2);
cy.get(".user-container").should("contain", "Adam Woodcock");
cy.get(".user-container").should("contain", "Kathleen Woodcock");
});
it("A blank search returns all users", () => {
cy.login();
cy.get("#searchButton").click();
cy.get(".user-container").should("have.length", 7);
cy.get(".user-container").should("contain", "Adam Woodcock");
cy.get(".user-container").should("contain", "Kathleen Woodcock");
cy.get(".user-container").should("contain", "Chris Coding");
cy.get(".user-container").should("contain", "Paul Coding");
cy.get(".user-container").should("contain", "Rob Oman");
cy.get(".user-container").should("contain", "George Hett");
cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
});
it("Visiting the search page without going through the search bar returns all users", () => {
cy.login();
cy.visit("/search");
cy.get(".user-container").should("have.length", 7);
cy.get(".user-container").should("contain", "Adam Woodcock");
cy.get(".user-container").should("contain", "Kathleen Woodcock");
cy.get(".user-container").should("contain", "Chris Coding");
cy.get(".user-container").should("contain", "Paul Coding");
cy.get(".user-container").should("contain", "Rob Oman");
cy.get(".user-container").should("contain", "George Hett");
cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
});
it("A search is not affected by adding non alphanumeric characters", () => {
cy.login();
cy.get("#searchBox").type("Chris /.,[] Coding");
cy.get("#searchButton").click();
cy.get(".user-container").should("have.length", 2);
cy.get(".user-container").should("contain", "Chris Coding");
cy.get(".user-container").should("contain", "Paul Coding");
});
it("A user's search returns results for each word", () => {
cy.login();
cy.get("#searchBox").type("Chris Woodcock");
cy.get("#searchButton").click();
cy.get(".user-container").should("have.length", 3);
cy.get(".user-container").should("contain", "Adam Woodcock");
cy.get(".user-container").should("contain", "Kathleen Woodcock");
cy.get(".user-container").should("contain", "Chris Coding");
});
});
请您建议我可以进行哪些调整才能使此代码正常运行
您可能会发现这效果更好,尽管我找不到任何由于异步处理而容易失败的地方。
我假设
User.find()
返回一个承诺。
const promises = searchArray.map((name) => {
return User.find({
firstName: { $regex: name, $options: "i" },
lastName: { $regex: name, $options: "i" },
})
})
Promise.all(promises).then((values) => {
const uniqueArray = values
.flat()
.filter((value, index, arr) => arr.indexOf(value) === index)
res.render("search/index", { users: uniqueArray });
})
cy.get(".user-container").should("have.length", 3);
应处理测试端的任何延迟,但如果执行多级搜索可能需要超过 4 秒的时间,您可能需要增加超时。
cy.get(".user-container", {timeout:10000})
.should("have.length", 3);
我设法通过将上面的内容重构为这个来解决我自己的问题,通过更改 foreach 循环来构建最终查询并将其传递给 find 语句,然后渲染效果非常好。我还重构了索引路线。
const User = require("../models/user");
const SearchController = {
Index: (req, res) => {
User.find().then((users) => {
res.render("search/index", { users: users });
});
},
Create: (req, res) => {
const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);
const findQuery = [];
searchArray.forEach((name) => {
const first = { firstName: { $regex: name, $options: "i" } };
const second = { lastName: { $regex: name, $options: "i" } };
findQuery.push(first, second);
});
User.find({ $or: findQuery }).then((users) => {
res.render("search/index", { users: users });
});
},
};
module.exports = SearchController;