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
Related
Currently I'm working on a project, and I'm looking for a better way to source code.
I wonder What is Different,
func (db *Database) FindData(ctx context.Context, filter *Data) (*Data, error) {
col := db.client.Database(DefaultDatabase).Collection(COLLECTION_DATA)
var data Data
err := col.FindOne(ctx, filter).Decode(&data)
if err != nil {
return nil, err
}
return &data, nil
}
and
func (db *Database) FindData(ctx context.Context, filter *Data) (*Data, error) {
col := db.client.Database(DefaultDatabase).Collection(COLLECTION_DATA)
res := col.FindOne(ctx, filter)
if err:= res.Err(); err != nil {
return nil, err
}
var data Data
err := res.Decode(&reason)
return &data, err
}
What are the possible differences, and which code is better?
I verified that both sources were the same, and realized that I didn't have to use the long version.
There is no need to implement ERROR processing because ERROR processing of the corresponding result is carried out in Decode().
Thanks for Comment :) Burak Serdar
Suppose I have a file that modifies database, should the functions share a single context or should each function have their own context?
Sharing context
var (
ctx = context.Background()
)
func test1() {
res, err := Collection.InsertOne(ctx, data)
}
func test2() {
res, err := Collection.InsertOne(ctx, data)
}
Or should it be like this?
func test1() {
res, err := Collection.InsertOne(context.Background(), data)
}
func test2() {
res, err := Collection.InsertOne(context.Background(), data)
}
Neither. Your context should be request-scoped (for whatever "request" means in your application) and passed down the call chain to each function.
func test1(ctx context.Context) {
res, err := Collection.InsertOne(ctx, data)
}
func test2(ctx context.Context) {
res, err := Collection.InsertOne(ctx, data)
}
If you're building a web server, as indicated in comments, you'll usually get your context from the HTTP request in your handler:
func myHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// now pass ctx to any fuction that needs it. This way, if the HTTP
// client/browser cancels the request, your downstream functions will
// be able to abort immediately, without wasting time finishing their
// work.
}
You should not use the first approach. Context is something to be passed down to functions, it should not be declared as a global variable.
The second approach can be used at times, especially if there is no request context. However, if multiple calls are handled within a single server context, you should pass down the context for that call to all the other calls getting a context, so when the context is canceled or expired, all calls would fail.
I store a double linked list in PostgreSQL. I have a Go API to manage this list.
There is a function that creates new Node (in specific position). Let's assume there is an INSERT SQL query inside of it.
Also, there is a function that deletes Node (by id). Let's assume there is a DELETE SQL query inside of it.
It is well known that if you need to move a Node to different position you should call DeleteNode() function and CreateNode() function. So there is the third function called MoveNode()
func MoveNode() error {
if err := DeleteNode(); err != nil {
return err
}
if err := CreateNode(); err != nil {
return err
}
return nil
}
But these functions (which are inside of MoveNode() should be called in one transaction.
Is there a way to "merge" functions in Go? Or what is the way to solve this problem (except copy & paste code from 2 functions to the third)?
p.s The idea is simple: you have two functions which do some SQL queries and you need to do these queries in one transaction (or call 2 functions in one transaction)
The better way to go about this here will be to move tx.Commit() outside the query execution functions (DeleteNode() and CreateNode() here)
Suggested Solution :
func MoveNode() error {
tx, err := db.Begin()
// err handling
res, err := DeleteNode(tx)
// err handling
res, err := CreateNode(tx)
// err handling
tx.Commit()
}
func DeleteNode(transactionFromDbBegin) (responseFromExec, errorFromExec) {
//...
}
func CreateNode(transactionFromDbBegin) (responseFromExec, errorFromExec) {
//...
}
This should do the trick.
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
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())