2017-11-15 17 views
2

私は最初のCRUD(ライブラリ)アプリケーションを構築しており、深くネストされたコールバックを避ける手段として約束されています。サーバーを起動するたびにDBにデータを入れようとしていますが、概念的に何か不足しているようです。forEachループが完了する前にPromiseが解決する

function seedBooks() { 
 
    return new Promise(function(resolve,reject){ 
 
     bookData.forEach(function(seed){ 
 
      Book.create(seed, function(err, newBook){ 
 
       if(err) { 
 
        reject(err); 
 
       } 
 
      }); 
 
     }); 
 
     resolve(); 
 
    }); 
 
}

この機能は、私がしようとしていますいくつかのいずれかです。

は、私はマングースを反復して使用してDBに保存したいbookData配列内の4つのオブジェクトを持っています私は約束を使っているのです。しかし、私は、seedBooks()が作成したサンプルブックのどこかの間に1と4で解決されることを発見

function seedDB() { 
 
    removeAllBooks() 
 
    .then(function(){ 
 
     return removeAllUsers(); 
 
    }) 
 
    .then(function(){ 
 
     return seedUsers(); 
 
    }) 
 
    .then(function(){ 
 
     return seedBooks(); 
 
    }) 
 
    .then(function(){ 
 
     return seedBookInstances(); 
 
    }); 
 
}

私が間違って約束&決意を理解するか、使用しているか?いどんな助けもありがとうございます。ありがとう!

答えて

1

非同期のforEached要求を開始した直後に、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.allを使用するだけです。あなたは、ループ内のすべてのあなたの要求をpromisifyする必要があるというアプローチでは、約束の配列を返し、その後_seedBookが約束の配列を返すPromise.all(_seedBooks()).then()を呼び出す:

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

編集:あなたのコードがある理由は、以下の説明一般的に、約束していないコードを約束に変換する方法についての作業と助言はありません。しかし、Mongooseは約束をしてくれるので、new Promiseの代わりにMongooseを使うべきです。それについては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 Sにアクセスすることを可能にするという利点を持っている、あなたがしたいはずです。あなたはマングースを使用している場合

1

、あなただけのこの操作を行うことができます。

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 
}); 
関連する問題