Coffescript Nested Do Loop / Async Nested Loop - coffeescript

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

Related

sql.Scan not returning ErrNoRows error when it should

I have a function GetAccount which is generated by sqlc.
When I call GetAccount(/*unused id*/), An ErrNoRows error should be returned. Instead I am getting no error and an Account with default values (zeros and empty strings) returned.
GetAccount implementation:
const getAccount = `-- name: GetAccount :one
SELECT id, owner, balance, currency, created_at
FROM accounts
WHERE id = $1
`
func (q *Queries) GetAccount(ctx context.Context, id int64) (Account, error) {
row := q.db.QueryRowContext(ctx, getAccount, id)
var i Account
err := row.Scan(
&i.ID,
&i.Owner,
&i.Balance,
&i.Currency,
&i.CreatedAt,
)
return i, err
}
Why I am not getting any error when there are no rows to return?
Edit:
As requested, here is how I am calling GetAccount. It is a Gin request handler.
type getAccountRequest struct {
ID int64 `uri:"id" binding:"required,min=1"`
}
func (server *Server) getAccount(ctx *gin.Context) {
var request getAccountRequest
err := ctx.ShouldBindUri(&request)
if err != nil {
ctx.JSON(http.StatusBadRequest, errorResponse(err))
return
}
account, err := server.store.GetAccount(ctx, request.ID) //<-called here
if err == sql.ErrNoRows {
ctx.JSON(http.StatusNotFound, errorResponse(err))
return
} else if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
ctx.JSON(http.StatusOK, account)
}
Edit 2:
For clarity, when I say
An ErrNoRows error should be returned
I state this because of the call to row.Scan which should produce the error.
Documentation:
func (r *Row) Scan(dest ...any) error
Scan copies the columns from the matched row into the values pointed at by dest. See the documentation on Rows.Scan for details. If more than one row matches the query, Scan uses the first row and discards the rest. If no row matches the query, Scan returns ErrNoRows.
You are overwriting the sql error:
account, err := server.store.GetAccount(ctx, request.ID) //<-called here
err = ctx.ShouldBindUri(&request)
if err == sql.ErrNoRows {
You should check the error immediately after the GetAccount call:
account, err := server.store.GetAccount(ctx, request.ID) //<-called here
if err == sql.ErrNoRows {

How to fetchall records in mongodb mgo.v2?

I Want to fetch all records in database By using NAME but, if I am using ALL it is showing 500 internal error but, if I Kept One(JSON) I am getting only one record. What is the solution to fetch all records by Name?
func (uc UserController) Filter(c *gin.Context) {
var name = c.Params.ByName("Name")
var json models.User
err := c.Bind(&json)
if err != nil {
log.Fatal("error")
return
}
json.Name = name
fi := bson.D{{"Name", name}}
err = uc.session.DB(DB_NAME).C(DB_COLLECTION).Find(fi).All(json)
if err == nil {
c.Writer.Header().Set("Content-Type", "application/json")
c.JSON(201, &json)
} else {
c.JSON(500, gin.H{"result": "An error occured"})
}
}
You should pass an array (var json []models.User) to the All(&json) function, but you're passing one item (var json models.User).

CoffeeScript declare and use global funcitons

Folks, given the following code... how would one re-use the returnResult and returnError functions? Is it possible to have their scope be global to all files that are required.
fs = require 'fs'
module.exports.syncJSON = (req, res)->
returnResult = (data) ->
res.send data
returnError = (data) ->
res.send data
jsonFileContents = fs.readFileSync('sample.json', 'utf8')
returnResult(jsonFileContents)
module.exports.asyncJSON = (req, res)->
fs.readFile 'sample.json', (err, data) ->
if err
returnError(err)
else
returnResult(data.toString())
returnResult = (data) ->
res.send data
returnError = (data) ->
res.send data
I think what you're asking about is how to use returnError and returnResult in both of the exports (.asyncJSON and .syncJSON). Globals are generally a bad idea. What if someone else overwrites your global? You'll have a weird and intermittent failure. If so, all you need to do is move them outside their current scope and pass in the response object:
s = require 'fs'
returnResult = (res, data)->
res.send data
returnError = (res, err) ->
res.send err
module.exports.syncJSON = (req, res)->
jsonFileContents = fs.readFileSync('sample.json', 'utf8')
returnResult(res, jsonFileContents)
module.exports.asyncJSON = (req, res)->
fs.readFile 'sample.json', (err, data) ->
if err
returnError(res, err)
else
returnResult(res, data.toString())

Get value from nested functions in Coffeescript

i want to get a result from another function (anonymous-function), but i don't know how because my result-function is a nested function. Maybe I have to use a callback somehow?
Here my code:
render: ->
console.log #getCommunities()
return this
getCommunities: ->
dpd.communities.get (result, err) ->
return console.log(err) if err
result
getCommunities() returns always 'undefined'.
Does anyone know how to solve this problem?
Thanks,
rojan
How about this?
render: ->
#getCommunities (err, result) ->
if err then throw err
console.log result
return this
getCommunities: (callback) ->
dpd.communities.get (result, err) ->
return console.log(err) if err
callback(null, result)
fyi, it's a best practice to pass err as the first arg to callbacks in node, assuming this is in fact node...just guessing by the err callback

$q defer and promises and how to use them to load the data for a controller before the view is rendered

This has been the most relevant thing I found: https://stackoverflow.com/a/11972028/110233
It seems to work fine when I only want to return one thing, but I'm unsure on how to return multiple things when the other things depend on the first thing.
Since that's kind of obtuse, here's a small example on what I'm currently doing:
window.EventRosterCtrl = ($scope, subevent) ->
$scope.subevent = subevent
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get {subevent_id: $route.current.pathParams.subevent_id}, (subevent) ->
deferred.resolve subevent
return deferred.promise
And here's an example of what I would want to do:
window.EventRosterCtrl = ($scope, subevent, addresses) ->
$scope.subevent = subevent
$scope.addresses = addresses
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get {subevent_id: $route.current.pathParams.subevent_id}, (subevent) ->
deferred.resolve subevent
return deferred.promise
addresses: (User) ->
deferred = $q.defer()
# how do you get subevent called first and how would you access it here?
for participant in subevent.participants
User.get {user_id: participant.user}, (user) ->
addresses[participant._id] = user.address
deferred.resolve addresses
return deferred.promise
you need to chain promisses using the .then()
var promise = firstOperation();
promise = promise.then(function(value) {
// do some more work
return value; // it can be another promise
});
return promise; // this one will be resolved when both steps are resolved
Ok, so a you can't control it that way, but a work around that comes to mind (when one resolution is dependent on another finishing first) is just put everything in one object and resolve that. What ended up working best for me was making a service, but to follow my original example:
window.EventRosterCtrl = ($scope, info) ->
$scope.subevent = info.subevent
$scope.addresses = info.addresses
EventRosterCtrl.resolve =
info: (SubEvent, User, $route, $q) ->
deferred = $q.defer()
resolvedInfo = {}
SubEvent.get {subevent_id: $route.current.pathParams.subevent_id}, (subevent) ->
resolvedInfo.subevent = subevent
for participant in subevent.participants
User.get {user_id: participant.user}, (user) ->
addresses[participant._id] = user.address
if addresses.length is subevent.participants.length
resolvedInfo.addresses = addresses
deferred.resolve resolvedInfo
return deferred.promise
The EventRosterCtrl is only initialized when the subevent is ready, so the following should work:
window.EventRosterCtrl = ($scope, subevent) ->
$scope.subevent = subevent
for participant in subevent.participants
User.get {user_id: participant.user}, (user) ->
$scope.addresses[participant._id] = user.address
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get {subevent_id: $route.current.pathParams.subevent_id}, (subevent) ->
deferred.resolve subevent
return deferred.promise