问题描述:

I want to save into two collections in my mongoDB. This operations are async so I use for and do in coffee.

for machine in machines

do(machine) ->

//if machine does not exist

for part in machine.parts

do(part) ->

//if not part not exists --> save

//push part to machine parts list

//save machine

The machine parts are empty later in the db. How can I make the first do loop wait for the second do loop to finish?

EDIT Real Code Example:

 recipeModel = require('../models/recipe.model')

ingredientModel = require('../models/ingredient.model')

#Save Recipe into the database

async.map recipes, (recipe, next) ->

recipeDBObject = new recipeModel()

recipeDBObject.href = recipe.href

recipeDBObject.ingredients = []

recipeModel.find({ href: recipe.href }, (err, recipeFound) ->

return next err if err

return next null, recipeFound if recipeFound.length > 0

recipeDBObject.title = recipe.title

ingredientsPushArray = []

console.log recipe.href

async.map recipe.zutaten, (ingredient, cb) ->

#Save all ingredients

ingredient.idName = ingredient.name.replace(/[^a-zA-Z0-9]+/gi, "").toLowerCase()

ingredientModel.find({ idName: ingredient.idName }, (err, ingredientFound) ->

return next err if err

if ingredientFound.length >0

ingredientDBObject = ingredientFound[0]

else

ingredientDBObject = new ingredientModel()

ingredientDBObject.name = ingredient.name

ingredientDBObject.save()

recipeDBObject.ingredients.push({"idName":ingredient.idName, "name":ingredient.name, "amount":ingredient.amount})

return cb(null, true)

)

recipeDBObject.ingredients = ingredientsPushArray

recipeDBObject.save()

return next(null, true)

)

I still don't get it working. Recipes are saved, node builds the ingredients array but it neither saves the ingredients nor does it save the array into the recipes.

EDIT 2:

 async.map recipes,

(recipe, next) ->

recipeDBObject = new recipeModel()

recipeDBObject.href = recipe.href

recipeDBObject.ingredients = []

recipeModel.find({ href: recipe.href }, (err, recipeFound) ->

return next err if err

return next null, recipeFound if recipeFound.length > 0

recipeDBObject.title = recipe.title

ingredientsPushArray = []

ingredientsArray = []

async.map recipe.zutaten,

(ingredient, cb) ->

#Save all ingredients

ingredient.idName = ingredient.name.replace(/[^a-zA-Z0-9]+/gi, "").toLowerCase()

ingredientModel.find({ idName: ingredient.idName }, (err, ingredientFound) ->

return next err if err

ingredientsArray.push({"idName":ingredient.idName, "name":ingredient.name, "amount":ingredient.amount})

if ingredientFound.length >0

return cb(null, true)

else

ingredientDBObject = new ingredientModel()

ingredientDBObject.name = ingredient.name

ingredientDBObject.idName = ingredient.idName

ingredientDBObject.save((err) ->

#console.log "some erros because required is empty" if err

return cb err if err

#console.log "ingredient saved"

return cb(null, true)

)

(err, ingredientsArray) ->

console.log "This is never logged"

return err if err

recipeDBObject.ingredients = ingredientsArray

recipeDBObject.save((err)->

return err if err

return next(null, true)

)

)

)

(err) ->

console.log "show me the errors: ", err if err

Now the ingredients are saved but the recipes aren't.

Interesting ressources:

http://www.hacksparrow.com/managing-nested-asynchronous-callbacks-in-node-js.html

网友答案:

The easiest way is to use some module for for managing asynchronous control flow, for example

  • async
  • promise-based solutions (e.g. when, bluebird, Q)
  • co for ES6 generator-based control flow

Here are some simple examples.

Using async.map

async = require 'async'

async.map machines,
  (machine, next) ->
    # Process single machine object
    Machine.findById machine._id, (err, found) ->
      return next err if err # return error immediately
      return next null, found if found # return the object we found
      async.map machine.parts,
        (part, cb) ->
          # Save part to DB and call cb callback afterward
          Part.create part, cb
        (err, parts) ->
          return next err if err # propagate error to the next handler
          # All parts have been saved successfully
          machine.parts = parts
          # Save machine to DB and call next callback afterward
          Machine.create machine, next
  (err, machines) ->
    if err
      # Something went wrong
    else
      # All machine objects have been processed successfully

Using promises and when module

When = require 'when'

machines_to_save = When.filter machines, ({_id}) ->
  Machine.findById(_id).then (found) -> not found
When.map machines_to_save, (machine) ->
  When.map machine.parts, (part) ->
    Part.create part
  .then (parts) ->
    machine.parts = parts
    Machine.create machine
.then (saved_machines) ->
  # All machines are saved
.otherwice (err) ->
  # Something went wrong
相关阅读:
Top