我正在构建我的第一个CRUD(库)应用程序,并且最近了解了promises作为避免深层嵌套回调的方法。我每次服务器启动时都试图用一些数据为我的数据库播种,但我似乎在概念上遗漏了一些东西。
我在bookData
数组中有四个对象,我想迭代并使用Mongoose保存到数据库中:
function seedBooks() {
return new Promise(function(resolve,reject){
bookData.forEach(function(seed){
Book.create(seed, function(err, newBook){
if(err) {
reject(err);
}
});
});
resolve();
});
}
这个函数是我尝试连接在一起的少数几个函数之一,这就是我使用promises的原因。但我发现seedBooks()
解析了所创建的样本书中的1到4个
function seedDB() {
removeAllBooks()
.then(function(){
return removeAllUsers();
})
.then(function(){
return seedUsers();
})
.then(function(){
return seedBooks();
})
.then(function(){
return seedBookInstances();
});
}
我是否理解或使用承诺&解决不正确?任何帮助表示赞赏。谢谢!
答案 0 :(得分:2)
编辑:下面解释了为什么您的代码无法正常工作,以及一般来说如何将非承诺代码转换为承诺的建议。但是,由于Mongoose产生了承诺,你应该使用它们而不是使用new Promise
。有关此问题,请参阅Olegzandr's answer。
承诺立即解决,因为您立即致电resolve()
。
将非承诺转换为承诺时的经验法则是宣传非承诺代码的最小部分。在这种情况下,它意味着宣传代码以保存单个项目。如果您这样做,收集的地方resolve()
变得清晰:
function seedBook(seed) {
return new Promise(function (resolve, reject) {
Book.create(seed, function (err, newBook) {
if (err) { reject(err); } else { resolve(newBook); }
});
});
}
function seedBooks() {
return Promise.all(bookData.map(seedBook));
}
如果您愿意,还可以让您访问返回的newBook
。
答案 1 :(得分:1)
您在启动asEached请求后立即同步解析Promise,这些请求是异步的。您可以尝试以下方法:
function seedBooks() {
return new Promise(function(resolve,reject){
var count = 0, length = bookData.length;
bookData.forEach(function(seed){
Book.create(seed, function(err, newBook){
if(err) {
reject(err);
return;
}
if(count++ >= length ) {
resolve();
}
});
});
});
}
只有在完成所有异步请求后,才会解决Promise。
另一种选择就是使用Promise.all。在这种方法中,你需要在循环中宣传你的所有请求,返回一个Promises数组,然后调用Promise.all(_seedBooks()).then()
,其中_seedBook
返回一个Promises数组:
function _seedBooks() {
return bookData.map(function(seed) {
return new Promise(function(resolve, reject) {
Book.create(seed, function(err, newBook) {
if(err) {
reject(err);
return;
}
resolve(newBook);
});
});
});
}
Promise.all(_seedBooks())
.then(function(result) { /* result is the array of newBook objects */ })
.catch(function(error) { /* error is the first rejected err */ })
答案 2 :(得分:1)
如果你使用的是Mongoose,你可以这样做:
const saveBooks = function(books) {
return books.map(function(seed) {
return Book.create(seed); // returns a promise
});
});
}
return Promise.all(saveBooks(books)).then(function(){
// all books are saved
});