NodeJS return values mySQL - mysql

i have a question regarding nodeJS.
I have a LOOP in nodeJS that iterates mySQL table and depending on the result executes a specific query.
var query = "SELECT field1,fields2,field3 FROM database.table1";
mySQLconnection.query(query, function (err, data) {
if (err)throw err;
if (data.length != 0) {
for (var i = 0; i <= data.length - 1; i++) {
doFunction1(data[i].field1, data[i].field2, data[i].field3, function (func1data) {
if (func1data == false) {
doFunction2(data[i].field1, data[i].field2, data[i].field3, function (func2data) {
if (func2data == false) {
doFunction3(data[i].field1, data[i].field2, data[i].field3, function (func1data) {
});
}
});
}
});
}
}
});
The problem with the above approach is that it will not wait for the result from the first doFunction1, but rather it will continue with the i++

Either of your two functions doFunction1 or doFunction2 intiates some kind of asynchronous calls. Looks like you are not familiar with asynchronous behaviour of javascript. You can use the async.each to handle these type of situations.

for (var i=0; i<10000; i++) {
console.log(i);
some_async_function_call(i);
}
Basically this code initiates 10000 requests to execute your asyc functions. There's no guarantee your code will be executed before the for loop is finished.
What you need to do is to chain your async function calls so it will do things sequentially. There are multiple ways to achieve this. For example async.js or bluebird.js
async.js: series, waterfall, parallel... etc
https://github.com/caolan/async#waterfall
async.waterfall([
function(callback) {
callback(null, 'one', 'two');
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
},
function(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
bluebird.js
https://github.com/petkaantonov/bluebird
var loop = function(){
// check loop conditions, return when the loop is finished
if (finished_loop) return Promise.resolve();
return Promise.promisify(your_function)()
.then(loop)
}

why do you want callbacks here in for loop. Write straight forward code which will be executed sequentially otherwise this code executes asynchronously.

At the end i went with a array and counter, when counter reaches the array length, it would restart it self. Basically recursive function.
Thanks for your help

Related

Angular - How to set up a parallel for loop in event binding function?

I have a function that expands every RowCol object in a FlexGridDetailProvider upon click. Right now, performance is bad with the way data binding works on FlexGrid rows, so I'm looking to improve performance by parallelizing each statement in the for loop.
Here's the typescript function:
if (thisDetailProvider!= null) {
setTimeout(() => {
try {
for (var t = 0; t < grid.rows.length; t++) {
if (thisDetailProvider.isDetailAvailable(t)) {
thisDetailProvider.showDetail(t);
this.gridSelectionService.clearSelectionFromGrids(thisDetailProvider.grid);
}
}
} catch (err) { console.log(err); }
}, 100);
}
I'd like the solution to be as simple as using the Parallel.For loop provided with C#. The solutions I've found so far require turning the event binding function into an asynchronous function, but I'd like to avoid introducing that complexity if there is a simpler way.
You can use async function to achieve the reduced code complexity. It is same as promise.
// `async` function | define a function start with `async` keyword
async myAsyncFunc() {
// #1 `async` ensures that the function returns a promise,
// even without explicitly return
return 123;
// #2 we can also `explicitly` return a promise
// this works same as above return
// return Promise.resolve(123);
// we can do both the ways but
// as `async` ensures that the function returns a promise
// so why to write extra code to return explicitly
}
// calling a function - and to get return result call then()
// the function inside then() will return the value
myAsyncFunc().then((returnVal) => {
console.log(returnVal); // 123
});
async yourFunction(){
for (var t = 0; t < grid.rows.length; t++) {
if (thisDetailProvider.isDetailAvailable(t)) {
thisDetailProvider.showDetail(t);
this.gridSelectionService.clearSelectionFromGrids(thisDetailProvider.grid);
}
}
}
In your case, I guess you can ignore the returning part which involves then

How do I use promises in a Chrome extension?

What I am trying to do is create a chrome extension that creates new, nested, bookmark folders, using promises.
The function to do this is chrome.bookmarks.create(). However I cannot just
loop this function, because chrome.bookmarks.create is asynchronous. I need to wait until the folder is created, and get its new ID, before going on to its children.
Promises seem to be the way to go. Unfortunately I cannot find a minimal working example using an asynchronous call with its own callback like chrome.bookmarks.create.
I have read some tutorials 1, 2, 3, 4. I have searched stackOverflow but all the questions do not seem to be about plain vanilla promises with the chrome extension library.
I do not want to use a plugin or library: no node.js or jquery or Q or whatever.
I have tried following the examples in the tutorials but many things do not make sense. For example, the tutorial states:
The promise constructor takes one argument—a callback with two
parameters: resolve and reject.
But then I see examples like this:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
How this works is a mystery to me.
Also, how can you call resolve() when its never been defined? No example in the tutorials seem to match real life code. Another example is:
function isUserTooYoung(id) {
return openDatabase() // returns a promise
.then(function(col) {return find(col, {'id': id});})
How do I pass in col, or get any results!
So if anyone can give me a minimal working example of promises with an asynchronous function with its own callback, it would be greatly appreciated.
SO wants code, so here is my non-working attempt:
//loop through all
function createBookmarks(nodes, parentid){
var jlen = nodes.length;
var i;
var node;
for(var i = 0; i < nodes.length; i++){
var node = nodes[i];
createBookmark(node, parentid);
}
}
//singular create
function createBookmark(node, parentid){
var bookmark = {
parentId : parentid,
index : node['index'],
title : node['title'],
url : node['url']
}
var callback = function(result){
console.log("creation callback happened.");
return result.id; //pass ID to the callback, too
}
var promise = new Promise(function(resolve, reject) {
var newid = chrome.bookmarks.create(bookmark, callback)
if (newid){
console.log("Creating children with new id: " + newid);
resolve( createBookmarks(bookmark.children, newid));
}
});
}
//allnodes already exists
createBookmarks(allnodes[0],"0");
Just doesn't work. The result from the callback is always undefined, which it should be, and I do not see how a promise object changes anything. I am equally mystified when I try to use promise.then().
var newid = promise.then( //wait for a response?
function(result){
return chrome.bookmarks.create(bookmark, callback);
}
).catch(function(error){
console.log("error " + error);
});
if (node.children) createBookmarks(node.children, newid);
Again, newid is always undefined, because of course bookmarks.create() is asynchronous.
Thank you for any help you can offer.
Honestly, you should just use the web extension polyfill. Manually promisifying the chrome APIs is a waste of time and error prone.
If you're absolutely insistent, this is an example of how you'd promisify chrome.bookmarks.create. For other chrome.* APIs, you also have to reject the callback's error argument.
function createBookmark(bookmark) {
return new Promise(function(resolve, reject) {
try {
chrome.bookmarks.create(bookmark, function (result) {
if (chrome.runtime.lastError) reject(chrome.runtime.lastError)
else resolve(result)
})
} catch (error) {
reject(error)
}
})
}
createBookmark({})
.then(function (result) {
console.log(result)
}).catch(function (error) {
console.log(error)
})
To create multiple bookmarks, you could then:
function createBookmarks(bookmarks) {
return Promise.all(
bookmarks.map(function (bookmark) {
return createBookmark(bookmark)
})
)
}
createBookmarks([{}, {}, {}, {}])
.catch(function (error) {
console.log(error)
})
Take the advantage of the convention that the callback function always be the last argument, I use a simple helper function to promisify the chrome API:
function toPromise(api) {
return (...args) => {
return new Promise((resolve) => {
api(...args, resolve);
});
};
}
and use it like:
toPromise(chrome.bookmarks.create)(bookmark).then(...);
In my use case, it just works most of the time.

Break a Bluebird .each() process

I'm converting from Async to Bluebird and can't figure out how to break a loop
Here's what I'm trying to achieve:
Loop through an array of data.
For each item, check if it exists on DB.
Add one item to the DB (first item that doesn't exist), and exit the .each() loop.
Any help will be highly appreciated.
Bluebird does not have a built in function for that type of operation and it's a little bit difficult to fit into the promise iteration model because iterators return a single value (a promise) which doesn't really give you the opportunity to communicate back both success/error and stop iteration.
Use Rejection to Stop Iteration
You could use Promise.each(), but you'd have to use a coded rejection in order to stop the iteration like this:
var data = [...];
Promise.each(data, function(item, index, length) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
// successfully added item to DB
// lets reject now to stop the iteration
// but reject with a custom signature that can be discerned from an actual error
throw {code: "success", index: index};
});
}
})
}).then(function() {
// finished the iteration, but nothing was added to the DB
}, function(err) {
if (typeof err === "object" && err.code === "success") {
// success
} else {
// some sort of error here
}
});
This structure could be put into a reusable function/method if you have to use it regularly. You just have to adopt a convention for a rejected promise that really just meant to stop the iteration successfully rather than an actual error.
This does seem like an interesting and not all that uncommon need, but I haven't seen any particular defined structure with Promises for handling this type of issue.
If it feels like overloading a reject as in the above scenario is too much of a hack (which it sort of does), then you could write your own iteration method that uses a resolved value convention to tell the iterator when to stop:
Custom Iteration
Promise.eachStop = function(array, fn) {
var index = 0;
return new Promise(function(resolve, reject) {
function next() {
if (index < array.length) {
// chain next promise
fn(array[index], index, array.length).then(function(result) {
if (typeof result === "object" && result.stopIteration === true) {
// stopped after processing index item
resolve(index);
} else {
// do next iteration
++index;
next();
}
}, reject);
} else {
// finished iteration without stopping
resolve(null);
}
}
// start the iteration
next();
});
}
Here if the iterator resolves with a value that is an object has has a property stopIteration: true, then the iterator will stop.
The final promise will reject if there's an error anywhere and will resolve with a value of null if the iterator finished and never stopped or with a number that is the index where the iteration was stopped.
You would use that like this:
Promise.eachStop(data, function(item, index, length) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
// return special coded object that has stopIteration: true
// to tell the iteration engine to stop
return {stopIteration: true};
});
}
})
}).then(function(result) {
if (result === null) {
// finished the iteration, but nothing was added to the DB
} else {
// added result item to the database and then stopped further processing
}
}, function(err) {
// error
});
Flag Variable That Tells Iterator Whether to Skip Its Work
In thinking about this some more, I came up with another way to do this by allowing the Promise.each() iteration to run to completion, but setting a higher scoped variable that tells your iterator when it should skip its work:
var data = [...];
// set property to indicate whether we're done or not
data.done = false;
Promise.each(data, function(item, index, length) {
if (!data.done) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
data.done = true;
});
}
})
}
}).then(function() {
// finished
}, function(err) {
// error
});

Async and Knex: how they work ?

I parse an json object and for each element, i need to execute many queries.
In first, a "select" query and depending on the result, i execute an insert or an update.
I would like use async.js and knex.js
The issue it's the order of execution is not the searched order
async.each(newContent,function(e){
//var e=JSON.stringify(element),
var z=-1,
devicepresenceId = e.device_presence_id;
//console.log(e);
async.waterfall([
function(cb) {
knex('jos_joomrh_event_employee_hours_presence')
.whereRaw('device_presence_id=?', devicepresenceId)
.select('id', 'applied_at', 'applied_at_end')
.debug()
.then(function (rows) {
console.log(rows);
z = _.keys(rows).length;
console.log('rows0', z);
cb(null,z);
})
.catch(function (e) {
console.log(e)
reject(e)
})
cb(null,z);
},
function(z,cb){
console.log('z',z);
if (parseInt(z)==0)
{
console.log('insertHoursPresence');
//insertHoursPresence(e)
}
else{
console.log('updateHoursPresence');
//updateHoursPresence(e)
}
cb(null,'two')
}
],
function(err,z){
if(err)console.log(err);
console.log(z);
}
)}
)}
In fact; it executed the second function and and the cb function and after the first function with knex.:
Thanks for your help
Mdouke
In the knex part, you have a call to "cb(null,z)", you have to "move" that call inside catch function (but replacing reject(e) part). Your problem is that you're calling cb() function outside knex, of course it is called immediately independent of knex result)

Using jQuery.when with array of deferred objects causes weird happenings with local variables

Let's say I have a site which saves phone numbers via an HTTP call to a service and the service returns the new id of the telephone number entry for binding to the telephone number on the page.
The telephones, in this case, are stored in an array called 'telephones' and datacontext.telephones.updateData sends the telephone to the server inside a $.Deferred([service call logic]).promise();
uploadTelephones = function (deffered) {
for (var i = 0; i < telephones.length; i++){
deffered.push(datacontext.telephones.updateData(telephones[i], {
success: function (response) {
telephones[i].telephoneId = response;
},
error: function () {
logger.error('Stuff errored');
}
}));
}
}
Now if I call:
function(){
var deferreds = [];
uploadTelephones(deferreds);
$.when.apply($, deferreds)
.then(function () {
editing(false);
complete();
},
function () {
complete();
});
}
A weird thing happens. All the telephones are sent back to the service and are saved. When the 'success' callback in uploadTelephones method is called with the new id as 'response', no matter which telephone the query relates to, the value of i is always telephones.length+1 and the line
telephones[i].telephoneId = response;
throws an error because telephones[i] does not exist.
Can anyone tell me how to keep the individual values of i in the success callback?
All of your closures (your anonymous functions capturing a variable in the local scope) refer to the same index variable, which will have the value of telephones.length after loop execution. What you need is to create a different variable for every pass through the for loop saving the value of i at the instance of creation at for later use.
To create a new different variable, the easiest way is to create an anonymous function with the code that is to capture the value at that particular place in the loop and immediately execute it.
either this:
for (var i = 0; i < telephones.length; i++)
{
(function () {
var saved = i;
deffered.push(datacontext.telephones.updateData(telephones[saved],
{
success: function (response)
{
telephones[saved].telephoneId = response;
},
error: function ()
{
logger.error('Stuff errored ');
}
}));
})();
}
or this:
for (var i = 0; i < telephones.length; i++)
{
(function (saved) {
deffered.push(datacontext.telephones.updateData(telephones[saved],
{
success: function (response)
{
telephones[saved].telephoneId = response;
},
error: function ()
{
logger.error('Stuff errored ');
}
}));
})(i);
}
should work.
Now, that's a bit ugly, though. Since you are already going through the process of executing an anonymous function over and over, if you want your code to be a little bit cleaner, you might want to look at Array.forEach and just use whatever arguments are passed in, or just use jQuery.each as you are already using jQuery.