Coffeescript嵌套Do循环/异步嵌套循环

时间:2015-04-01 08:03:10

标签: coffeescript

我想在我的mongoDB中保存两个集合。这个操作是异步的,所以我在咖啡中使用和做。

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

以后机器部件在数据库中是空的。如何让第一个do循环等待第二个do循环完成?

编辑真实代码示例:

  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)
    )

我仍然无法让它发挥作用。食谱被保存,节点构建成分阵列但它既不保存成分也不将数组保存到食谱中。

编辑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

现在成分已经保存,但配方不是。

有趣的资源: http://www.hacksparrow.com/managing-nested-asynchronous-callbacks-in-node-js.html

1 个答案:

答案 0 :(得分:2)

最简单的方法是使用某个模块来管理asynchronous control flow,例如

  • async
  • 基于承诺的解决方案(例如whenbluebirdQ
  • co用于基于ES6生成器的控制流程

以下是一些简单的例子。

使用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

使用promises和when模块

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