2016-08-17 2 views
1

Я пытаюсь вставить документы в MongoDB, используя их модели Mongoose, и я хотел бы использовать обещания. Поскольку эти данные берутся из базы данных MSSQL, документы в каждом наборе имеют отношения внешних ключей с документами в других наборах.Как выполнить Promise.all несколько массивов вкладышей для документов мангуста

Вот пример кода:

const Promise = require('bluebird'); 
const mongoose = require('mongoose'); 
const Make = Promise.promisifyAll(require('../models/make-model')); 
const Nameplate = Promise.promisifyAll(require('../models/nameplate-model')); 
const Vehicle = Promise.promisifyAll(require('../models/vehicle-model')); 

const { makes, nameplates, vehicles } = require('./sqlExport.json'); 

const logErr = (err) => console.error(err); 

Promise.resolve(
    mongoose.connection.db.dropDatabase() 
) 
.then(() => (
    Promise.all(
    makes.map(make => (
     Make.create(make).then(makeRes => console.log(`Created make ${makeRes}`)) 
    )) 
)), 
    logErr 
) 
.then(() => (
    Promise.all(
    nameplates.map(nameplate => { 
     const { sqlMakeId, sqlModelId, sqlSubModelId } = nameplate; 
     return Make.find({ sqlMakeId }) 
     .then(makeRes => { 
      if (makeRes.length !== 1) throw new Error(`duplicate or non-existent key for make.sqlMakeId: ${sqlMakeId}`); 
      const finalNameplate = Object.assign({}, nameplate, { mongoMakeId: makeRes[0]._id }); 
      return Nameplate.create(finalNameplate); 
     }) 
     .then(nameplateRes => { 
      console.log(`Created nameplate ${nameplateRes}`); 
     }); 
    }) 
)), 
    logErr 
) 
.then(() => (
    Promise.all(
    vehicles.map(vehicle => { 
     const { sqlVehicleId, sqlMakeId, sqlSubModelId } = vehicle; 
     const extraParams = {}; 
     return Make.find({ sqlMakeId }) 
     .then(makeRes => { 
      if (makeRes.length !== 1) throw new Error(`duplicate or non-existent key for make.sqlMakeId: ${sqlMakeId}`); 
      extraParams.mongoMakeId = makeRes[0]._id; 
      return Nameplate.find({ sqlSubModelId }); 
     }) 
     .then(nameplateRes => { 
      if (makeRes.length !== 1) throw new Error(`duplicate or non-existent key for nameplate.sqlSubModelId: ${sqlSubModelId}`); 
      extraParams.mongoNameplateId = nameplateRes[0]._id; 
      const finalVehicle = Object.assign({}, vehicle, extraParams); 
      return Vehicle.create(finalVehicle); 
     }) 
     .then(vehicleRes => { 
      console.log(`Created vehicle ${vehicleRes}`); 
     }); 
    }) 
)), 
    logErr 
) 
.catch(logErr); 

Проблема заключается в том, что иногда машина вставляет все бежать перед любой из паспортных вставок, и, таким образом, не может найти правильный _id документа для mongoNameplateId.

Полный код здесь: https://gist.github.com/jeremyjs/1d5509350d3cae69d0e83f1d6478eeb2

+0

похоже, что он должен работать на меня. это помогло бы, если бы вы могли разделить код на barebones, чтобы облегчить отладку. Единственное, что мне нравится делать, это заменить все ваши асинхронные вызовы вызовами setTimeout, которые разрешают обещание через секунду или около того, и печатать сообщение о том, что они заменяют, то есть 'console.log (« Make.find ('blah') ") ' – thedarklord47

+2

« Идентификационная табличка »и« Транспортные средства »API являются многообещающими, но нет доказательств того, что вызывается многообещающие методы. Должен ли 'Nameplate.create()' быть 'Nameplate.createAsync()' и 'Vehicle.create()' быть 'Vehicle.createAsync()'? –

+1

@ Roamer-1888 хороший звонок. Я никогда не использовал bluebird, но, глядя на документы, он указывает: «Обратите внимание, что исходные методы объекта не перезаписываются, но новые методы создаются с помощью суффикса Async. Например, если вы promisifyAll для объекта node.js fs, используйте fs.statAsync, чтобы вызвать метод promisified stat.' – thedarklord47

ответ

0

Я получил его на работу, добавив следующую строку ниже моих мангустов и Bluebird требуют утверждения:

mongoose.Promise = Promise;

Документация здесь: http://mongoosejs.com/docs/promises.html

В в этом случае шаблон Promise.promisifyAll от синей птицы не нужен.

+0

Приятный и простой, но если это работает, то кажется вероятным, что также будет работать функция «mpromise» по умолчанию. Вы пробовали ни с Bluebird, ни с линией 'mongoose.Promise = Promise'? –

+0

@ Roamer-1888 Действительно, он работает с mpromise, но Bluebird более эффективен, чем mpromise. –

Смежные вопросы