我对节点和异步编程非常陌生。我正在尝试使用伪造者js将多个用户对象记录(假设5)添加到mongodb(使用mongoose)中,以播种我的数据库。 我想使它尽可能通用,以便可以显式运行脚本来播种数据库。 我面临的问题(经过大量尝试和研究之后)是我的数据库进程(无论是创建还是保存)正在异步模式下执行,到那时,猫鼬断开进程也得到了调用。
用户数据加载js脚本的代码段:
const User = require("../models/User");
const faker = require("faker");
const bcrypt = require("bcryptjs");
const async = require("async");
module.exports = seedUser;
function seedUser(randomSeed, numData) {
return new Promise(resolve => {
faker.seed(randomSeed);
console.log(randomSeed, numData);
const userList = new Array(numData);
// for (let i = 0; i < numData; i++) {
// resolvedUser[i] = await loadUser(i);
// console.log("I am outer " + resolvedUser[i]);
// await User.create(resolvedUser[i], (err, user) => {
// if (err) throw err;
// console.log("I am saved " + user);
// });
// }
async.forEachOfSeries(userList, (val, key, callback) => {
console.log("Length " + userList.length);
hashUser(key).then(resolvedUser => {
if (resolvedUser) {
console.log("I am resolved " + key + resolvedUser);
userList[key] = resolvedUser;
createUser(resolvedUser).then(data => console.log("Create " + data));
// new User(resolvedUser)
// .save()
// .then(user => {
// userList.push(user);
// //val = user;
// console.log("I am saved " + user);
// })
// .catch(err => console.log(err));
}
});
console.log("I am outer " + key);
// await User.create(resolvedUser, (err, user) => {
// if (err) throw err;
// console.log("I am saved " + user);
// userList.push(user);
// });
});
console.log("whole list1 is " + userList);
resolve(userList);
});
}
function createUser(userObj) {
return new Promise(resolve => {
const user = User.create(userObj).catch(err => console.log(err));
resolve(user);
});
}
function hashUser(i) {
return new Promise(resolve => {
console.log("Loop number " + i);
const newUser = new User({
name: faker.name.findName(),
email: faker.internet.email(),
avatar: faker.internet.avatar(),
password: "123456"
});
bcrypt.genSalt(10, (err, salt) => {
console.log(newUser.password);
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) {
console.log(err);
throw err;
}
console.log(hash);
newUser.password = hash;
console.log("I AM " + newUser);
// newUser
// .save()
// .then(user => {
// resolve(newUser);
// console.log("User Creation for " + user);
// })
// .catch(err => console.log(err));
//console.log("I AM in resolve" + resolve);
resolve(newUser);
});
});
});
}
我从包装器js脚本中调用此方法,如下所示:
const seedUserData = require("./User");
const seedAnotherUserData = require("./AnotherUser");
const mongoose = require("mongoose");
//DB Config
const db = require("../config/keys").mongoURI;
async function runProgram() {
return new Promise(async resolve => {
await mongoose
.connect(db)
.then(() => {
console.log("MongoDB connected successfully");
})
.catch(err => console.log(err));
const port = process.env.PORT || 5000;
//app.listen(port, () => console.log(`server running on port ${port}`));
await seedUserData(123, 5).then(list => {
if (list) {
console.log("List is" + list);
}
});
//.then(list => console.log("Done " + list));
//.then(() => mongoose.disconnect());
console.log("Done ");
console.log("MongoDB first save");
await mongoose.disconnect();
console.log("MongoDB Disconnected");
resolve("Done");
});
//Connect to mongoDB
//module.exports = seedUserData;
//module.exports = seedAnotherUserData;
//return "Completed";
}
runProgram().then(() => console.log("Completed"));
您愿意帮助我克服这个困难吗?我知道我缺少了一些东西,但无法弄清楚是什么。 问候, 酸
答案 0 :(得分:0)
我现在已经找到了答案,幸运的是,我关于异步等待和承诺的概念现在变得更加清晰。
对Promise.all的逻辑结构(现在正在插入到异步循环中)进行修改,并使用Promise.all。
修改后的代码段如下
const User = require("../models/User");
const faker = require("faker");
const bcrypt = require("bcryptjs");
const async = require("async");
module.exports = seedUser;
function seedUser(randomSeed, numData) {
return new Promise(async resolve => {
try {
faker.seed(randomSeed);
console.log(randomSeed, numData);
const userList = new Array(numData);
const resolvedUsers = new Array();
const userData = new Array();
console.log("type " + typeof resolvedUsers + resolvedUsers.length);
await (async () => {
await async.forEachOfSeries(userList, async (val, key, callback) => {
console.log("Length " + userList.length);
async function callback(resolvedUsers) {
var resolvedUser = await hashUser(key);
resolvedUsers.push(resolvedUser);
var user = await createUser(resolvedUser);
console.log("Create " + user);
userData.push(user);
return resolvedUsers;
//
}
await callback(resolvedUsers).then(result => {
console.log(
"I am resolved " +
key +
result[key] +
" and saved " +
userData[key]
);
if (result.length === numData) {
resolve(userData);
}
});
});
console.log(resolvedUsers);
})().then(() => {
console.log("see mee" + resolvedUsers.length);
});
// resolvePromise
// .then(() => {
// Promise.all(
// resolvedUsers.map(resolvedUser => {
// console.log("Inside all " + resolvedUser);
// createUser(resolvedUser).then(user => {
// console.log("Create " + user);
// userData.push(user);
// });
// })
// );
// })
// .then(() => {
// console.log("whole list1 is " + userData);
// resolve(userData);
// });
//console.log(next);
//await Promise.all([resolvePromise(), next()]);
// userData[key] = createUser(resolvedUser[key]);
//userList[key] = resolvedUser[key];
//console.log("I am outer " + key);
} catch (err) {
console.log(err);
}
});
}
function createUser(userObj) {
return new Promise(resolve => {
const user = User.create(userObj).catch(err => console.log(err));
resolve(user);
});
}
function hashUser(i) {
return new Promise(resolve => {
console.log("Loop number " + i);
const newUser = new User({
name: faker.name.findName(),
email: faker.internet.email(),
avatar: faker.internet.avatar(),
password: "123456"
});
bcrypt.genSalt(10, (err, salt) => {
console.log(newUser.password);
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) {
console.log(err);
throw err;
}
console.log(hash);
newUser.password = hash;
console.log("I AM " + newUser);
// newUser
// .save()
// .then(user => {
// resolve(newUser);
// console.log("User Creation for " + user);
// })
// .catch(err => console.log(err));
//console.log("I AM in resolve" + resolve);
resolve(newUser);
});
});
});
}
包装器如下:
const seedUserData = require("./User");
const seedAnotherUserData = require("./AnotherUser");
const mongoose = require("mongoose");
//DB Config
const db = require("../config/keys").mongoURI;
async function runProgram() {
// return new Promise(async resolve => {
try {
const conObj = mongoose.connect(db);
if (conObj) {
console.log("Mongo successfully connected" + conObj);
}
const port = process.env.PORT || 5000;
const userList = await seedUserData(23456, 50);
if (userList) {
console.log("List is" + userList);
}
//await Promise.all([conObj, userList]);
console.log("Done ");
console.log("MongoDB first save");
await mongoose.disconnect();
console.log("MongoDB Disconnected");
} catch (err) {
console.log(err);
}
// //app.listen(port, () => console.log(`server running on port ${port}`));
// await seedUserData(123, 5).then(list => {
// if (list) {
// console.log("List is" + list);
// }
// });
//.then(list => console.log("Done " + list));
//.then(() => mongoose.disconnect());
// resolve("Done");
// });
//Connect to mongoDB
//module.exports = seedUserData;
//module.exports = seedAnotherUserData;
//return "Completed";
}
runProgram().then(() => console.log("Completed"));
关于, 酸
答案 1 :(得分:0)
您的方法通常应该可以使用,但是您有很多不必要的语法,并且代码可能更简洁。例如,没有理由去做await (async () => { await fn(); })
,而只是去做await fn();
。另外,没有理由在异步/等待中使用async.forEachOfSeries()
,您可以只使用普通的旧for
循环。这里还有更多examples of using async/await with Mongoose。
答案 2 :(得分:0)
一些可以在哪里整理代码的指针:
bcrypt.genSalt()
表示为bcrypt.genSaltAsync()
,将bcrypt.hash()
表示为bcrypt.hashAsync()
。然后new Promise()
可以从更高级别的代码中消失。这是仅使用.then()
(没有异步/等待)的重做版本:
// First promisify bcrypt.genSalt() and bcrypt.hash()
bcrypt.genSaltAsync = (n) => {
return new Promise((resolve, reject) => {
bcrypt.genSalt(n, (err, salt) => {
if(err) reject(err);
else resolve(salt);
});
});
};
bcrypt.hashAsync = (password, salt) => {
return new Promise((resolve, reject) => {
bcrypt.hash(password, salt, (err, hash) => {
if(err) reject(err);
else resolve(hash);
});
});
};
然后,new Promise()
受到这两个保证的照顾,seedUser()
变得相当琐碎,即使没有hashUser()
和createUser()
作为单独的功能:
function seedUser(randomSeed, numData) {
faker.seed(randomSeed);
return Promise.all([...Array(numData)].map(() => {
const newUser = new User({
'name': faker.name.findName(),
'email': faker.internet.email(),
'avatar': faker.internet.avatar(),
'password': '123456'
});
return bcrypt.genSaltAsync(10)
.then(salt => bcryptAsync.hash(newUser.password, salt))
.then(hash => {
newUser.password = hash;
return User.create(newUser);
});
}));
}
您的“包装脚本”将按照以下方式整理:
function runProgram() {
return mongoose.connect(db)
.then(() => seedUserData(123, 5))
.then(() => mongoose.disconnect());
}
runProgram()
.then(() => {
console.log('Completed');
}, err => {
console.log(err);
});
注释
faker
不熟悉,并且我不了解User
的双重改组。faker
/ bcrypt
东西都可以并行完成。如果不是,请还原为async.forEachOfSeries()
(或类似名称)。Array(numData)
将不起作用)。或者,使用for
循环创建诺言数组。.then()
来支持async/await
。