How to use do/while Statement in an async function in JavaScript? - javascript

I have a an async function that checks if the id already exists in a table.
async function generateIdentifier () {
try {
let exists;
let id;
do {
id = someRandomStringGenerator();
const email = await Database.find({id});
if (email.length > 0) {
exists = true;
} else {
exists = false;
}
} while (exists);
return id;
} catch (e) {
throw e;
}
}
With the code above, the find method will return an array. If the array is empty, means no id is found. When an id is found, it should generate a new one until id is unique.
Also, yes this works though performance wise, are there better options with doing things like this?

I suggest you to use callback function as below. I took an API call to represent your Database request and I put the condition to loop until the string has the character v inside. With that it will work like a charm.
function loadData(callback){
$.ajax({url: "https://helloacm.com/api/random/?n=10", success: function(response){
callback(response);
}});
}
function checkData(response){
if(response.includes("w")){
console.log(response, "good");
} else {
console.log(response, "bad");
loadData(checkData);
}
}
function register(){
loadData(checkData);
}
register();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Yes this works, the entire selling point of async await is that you can make promise based code look like regular imperative constructs (such as while loops) just by adding the await keyword whenever you call out to another async function.
Performance wise, you could obviously benefit from generating the random ID on the server so that you always get an ID which is known to be unique in a single call. This is probably not a problem in practice as having more than 1 collision is likely to be very rare if the space of IDs is sufficiently large.

infinity do while is good when you have multiple cases when you need to change the condition of loop. In your case its simple. If found record, return otherwise do it again. However, the function name should represent it function. In your case is register, but actually you retrieving random record. Performance? Well, you are not really saving much here. You have couple async calls which will blocks your script until resolved. Example without dowhile https://stackblitz.com/edit/js-bgyman

Related

how to make wait javascript to finish all functions before return result

output = true;
if($("#password-field").css('display') != 'none') {
if(!($("#verificationCode").val())) {
output = false;
$("#code-error").html("required");
}
var codeverify = function(){
var code = document.getElementById("verificationCode").value;
coderesult
.confirm(code)
.then( function(result) {
if (result.user.uid) {
let phoneNumber = result.user.phoneNumber;
//alert(output);
alert("Verification done");
console.log(phoneNumber);
} else {
alert(output);
$("#code-error").html("no user");
output = false;
}
})
.catch(function(error) {
output = false;
$("#code-error").html("wrong");
alert(error.message);
});
}();
}
return output;
When i run this code everything works fine. but before checking the codeverify function it return the output to true even if the codeverify() function returns false
PS. I am using wizard form.
This comes down to how you write JavaScript code, I found that usually when to get to a point where my procedures are out of sync it means that I have done something wrong in previous steps. This is usually only fixed by refactoring.
Remember JavaScript does not behave the same as other languages.
What I can see from your procedure is that you are trying to do many things in one go.
Although I do not have a solution I have a suggestion, consider each action that you want your procedure to execute. Declare a separate function for each of these steps, even if your function only has one line to execute.
If there are dependencies make sure they can be resolved by parameterization.
And lastly, think pure functions. Try and structure every function to receive something and return something.
Another tip that I can give is, write your procedure to select and hold elements in variables until they are required. Consider what elements are required in execution, which of those are in the dom when execution starts and set them to variables before you start executing, then during execution if elements are added that are maybe required for later select them immediately after they are placed in the dom, this means that as your procedure executes all the ingredients are available to do whatever must be done they don't have to go find what they need on the fly.
Good Luck and happy coding.
Your coderesult.confirm(code) using promise(then & catch) so i assume it is asynchronous. You need to google yourself to learn what is async
One important thing of JS behavior is JS always process the rest of the code if there is a async function in between.
Sample:
console.log(1)
setTimeout(()=>{
console.log(2,"i suppose at position 2 but i'm at the last. This is because setTimeout is async function")
},1000)
console.log(3)
In your case, your codeverify function has async code (.confirm()) in between, so JS will process the code after codeverify (return output)until codeverify is fully completed.
Since your output was set at true since the beginning, it will return true from the last row of code return output before your codeverify completed, this is why you always get true. If you change the first row output = undefined, i believe you will see undefined result.
To solve this, one of the way is you can wrap the entire codeverify as Promise.
function codeverify(){
return new Promise((resolve,reject)=>{
var code = document.getElementById("verificationCode").value;
coderesult.confirm(code).then( function(result) {
if (result.user.uid) {
let phoneNumber = result.user.phoneNumber;
//alert(output);
alert("Verification done");
console.log(phoneNumber);
output = true
resolve(output)
} else {
alert(output);
$("#code-error").html("no user");
output = false;
resolve(output)
}
}).catch(function(error) {
output = false;
$("#code-error").html("wrong");
alert(error.message);
reject(output) //you can reject(error.message) so you can pass error message back.
});
})
}
You can execute the function like this:
codeverify().then(successData=>{
console.log(successData) //from what you resolve
}).catch(failedData=>{
console.log(failedData) //from what you reject
})
Lastly, take some time to study what is Asynchronous and What Promise to do with Async because it is everywhere in JS.

How is the following a pure function?

It states here that the following is a pure function:
function insert(DB, user) {
return function() {
throwIfUserExists(DB, user);
var savedUser = saveUser(DB, user);
return savedUser;
}
}
and that the following is an impure function:
function insert(user) {
if (DB.exists(user.id)) {
throw Error("users exists");
}
var id = DB.insert(user);
user.id = id;
return user;
}
I don't understand how the first function is pure, since it returns a function that produces side effects. Am I wrong and if not, how could the function be written to be pure?
A pure function is a function which:
Given the same input, will always return the same output.
Produces no side effects.
Now pay attention to the first point.
In your first example, as long as you keep sending in the same DB and user the output would be the same. The construction of savedUser or throwIfUserExists functions would affect the output of the first insert fn but the insert function in essence would be a pure function.
However, in the second function the output would be different for each call even though the user is the same. To be precise, the line user.id = id; is the one that is producing the "side effects".
Read Eric Elliot's article on pure functions : https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976

function that returns a value from webservice

I know this is a highly answered topic, but reading tons of posts I can't figure if my dilema has a solution as I want.
I want to write a simple function that returns the User Name passing the UserId. It will be used everywhere to multiple purposes.
function getUserName(userId) {
//...some code to retrieve the Name from a REST webservice like $.ajax or $.getJSON or anything else that helps me achieve my need
return name;
}
$('#txtUserName').val(getUserName(sessionStorage.userId));
//...
if (getUserName(sessionStorage.userId) == getUserName($('#inputUser').val())) {
alert('Error: User typed with the same name as '+ sessionStorage.userID);
}
I know that can rewrite it all to put callback's or whatever, but I want to know if there's any implementation that makes possible to write this simple function that returns a value from a PHP webService.
I imagine a function like this:
function getUserName(userId) {
var users ={
'me': 'Seak Oink'
, 'you': 'Who knows'
, 'jd': 'John doe'
};
return users[userId];
}
...but instead of having the fixed users object, i retrieve it from my php webService that gets it from a DB.
Using a callback, makes impossible to handle values. For example (if I'd use callback and assuming calling getUserName(userId, callback) handles the function call):
$('#txtUserName').val('');
getUserName(sessionStorage.userId, function(userName) {
$('#txtUserName').val(userName);
});
if ($('#txtUserName').val() == '') {
alert('user '+ sessionStorage.userId +' doesn't exist');
}
Instead, you could answer me to put it into the callback, but if need to call again my function, I must nest it to a callback again and again... I think it's a bad programming practice:
$('#txtUserName').val('');
getUserName(sessionStorage.userId, function(userName) {
$('#txtUserName').val(userName);
getUserName($('#inputUser').val(), function (userName2) {
if (userName2 == userName) {
alert('Error: User typed with the same name as '+ sessionStorage.userID);
}
//....here I must continue the code flow instead of continuing to caller's flow.
//...nesting, and more nesting... impossible to read code?¿¿?:
userpermission(userId, function(bAllowed) {
if (bAllowed) {
saveRecord(userId, sKey, sSomeText, function () {
alert('record saved -or not-');
// ...and continue nesting
});
} else {
alert('forbidden');
}
});
});
});
... instead of this simple code flow logic:
var lOk = false;
$('#txtUserName').val('');
$('#txtUserName').val(getUserName(sessionStorage.userId);
if ($('#inputUser').val() == getUserName($('#inputUser').val())) {
alert('Error: User typed with the same name as '+ sessionStorage.userID);
}
if (userpermission(userId)) {
lOk = saveRecord(userId, sKey, sSomeText);
} else {
alert('forbidden');
}
if (lOk) {
alert('record saved');
}
// ...continue the validation process or whatever
I understand the simple example of retrieving a value with a callback, but don't using it in code logic.
I've been read How do I return the response from an asynchronous call? and much more like that and understood, but I can't uderstand how to use retrieved values from different sources and apply the necessary logic. Basicly, how to order the chaos?
Looks like you're experiencing callback hell.
That happens when you have several asynchronous functions and you need to handle all their errors and success.
That's exactly for that case that promises have been invented.
If you don't have ES6, have a look on jquery promises, otherwise they are built-in : ES6 promise
They allow more readable, synchronous like code.
For example, you can do code like that:
$.when( // waits for two promises to be resolved
getUserName(userId)
.then(function(name) { // once name resolved, fetch profile (new promise)
return getUserProfile(name);
}),
getUserPoints(userId) // another independent promise
).done(function(userProfile, userPoints) { // the two above are done, I can move on and update the DOM
$("#profile").doSomething(userProfile);
$("#points").doOtherThing(userPoints);
});

Is there a way to check for if certain conditions are true on the second call of a function?

So I want to call a function
myfunction();
I want to be able to have my code call it once and be fine but if my code calls it a second time, I want to check to see if certain conditions are true and if they are, I want the function to not run. If these conditions aren't true, then I want the function to run as usual. I just want to know if something specific is true only for a second call to the function and not allow my function to run again until those conditions aren't true anymore.
if(condition) {
//don't run function code for as long as this is true.
}
else{
//business as usual, run the code
}
I want to do this always on the second call to the function. So first function call, no checking. On a second call, check. On a 3rd call no checking, on the 4th call check etc. Basically, every other call to the function, check to see if certain conditions are true
and if they are, don't run the function code. I would very much appreciate your response.
This is easy enough. Since what you're looking for is basically a function that modifies its behavior according to some internal state, it's an ideal application for objects:
var o = {
calls: 0,
fn: function(){
if(++this.calls%2){
console.log('odd call');
} else {
console.log('even call');
}
}
}
If you absolutely must have a function only (no object), you can use an immediately-invoked function expression (IIFE) to return a function:
var fn = (function(){
var calls = 0;
return function(){
if(++calls%2){
console.log('odd call');
} else {
console.log('even call');
}
}
})();
This has the advantage of encapsulating the calls variable: that can't be accessed or tampered without outside of the function.
As a cautionary note, what this achieves is called a "side effect": that is, the behavior of the function can no longer be predicted without understanding the details of the function. I'm not going to be dogmatic and say side effects are always bad, but you do have to be careful with them: make sure they make sense, and that your documentation is clear about what's happening.
you'd need an index variable outside of the function scope.
something like this:
var index = 0;
function myFunction() {
// TRUE on every second call
if (++index % 2 === 0) {
if (condition) {
// ....
} else {
// ...
}
}
// ....
}
You could use a closure: instead of
function f(x, y, z) {
... normal processing ...
}
create a closure that every other call will do the check
var f = (function(){
var do_check = true;
return function(x, y, z){
do_check = !do_check;
if (do_check && ... check ...) {
... special handling ...
} else {
... normal processing ...
};
})();
As others said however I'd say that keeping this behavior hidden inside the function seems a bad idea. Probably a better solution is just externalize (and document) the state.
This is not an answer to your question.
For sure there will be answers that tell you how to do this, but I'd argue that "The only winning move is not to play."
Having functions that behave differently between calls make will make your software very hard to work with (maintain, test, debug, reason about).
Should there be a reason for needing the function to behave differently between calls, make it about the state of the system, not purely about the function itself.
Agree with pkyeck, but why increase a var.
var checkCall = 1;
function myfunction(){
if(checkCall){
alert('true: so no code will run');
checkCall = 0;
} else {
alert('run the code');
checkCall = 1;
}
}

node, async programming, callback hell

i'm trying to understand callbacks and async programming, but I'm having a bit of trouble.
here's some pseudocode :
var lines = [];
var arrayOfFeedUrls = [url1,url2,...];
function scrape(url){
http.get(url, function(res) {
res.pipe(new FeedParser([options]))
.on('readable', function () {
var stream = this, item;
while (item=stream.read()) {
line = item.title;
lines.push(line);
}
});
});
});
for (i in arrayOfFeedUrls){
scrape(arrayOfFeedUrls[i];
}
console.log(lines.length);
It obviously returns 0, as the scrape function is executed asynchronously. I understand that much, but I've tried many intricated ways and can't figure out how to write it properly. Any help/explanation would be greatly appreciated. I've read (and I'm still reading) a lot of tutorials and examples, but I think the only way for me to get it is to write some code myself. If I solve this I'll post the answer.
You could want to check this article for an introduction in Node that might help you understand async programming in Node a little better.
As far as async programming goes, async is a very popular module in Node's userland which helps you write asynchronous code effortlessly. For instance (untested pseudo-code):
function scrape (done) {
http.get(url, done);
}
function parse (res, done) {
var lines = [];
res.pipe(new FeedParser([options]))
.on('readable', function () {
var stream = this, item;
while (item=stream.read()) {
line = item.title;
lines.push(line);
}
})
.on('end', function () {
done(null, lines);
});
}
function done (err, lines) {
if (err) { throw err; }
console.log(lines.length);
}
async.waterfall([scrape, parse], done);
This depends on if you want to scrape all urls in parallell or in series.
If you were to do it in series, you should think of it as this:
Start with the first url. Scrape. In the callback, scrape the next url. in the callback, scrape the next url.
This will give the notorious callback hell you are talking about, but that is the principle at least. That where librarires like async etc removes a lot of the headache.
When programming async calls in this manner, functions and instructions that you want to chain onto the end, such as console.log(lines.length);, must also be callbacks. So for instance, try something like this:
var lines = [];
var arrayOfFeedUrls = [url1,url2,...];
function scrape(url){
http.get(url, function(res) {
res.pipe(new FeedParser([options]))
.on('readable', function () {
var stream = this, item;
while (item=stream.read()) {
line = item.title;
lines.push(line);
done();
}
});
});
});
for (i in arrayOfFeedUrls){
scrape(arrayOfFeedUrls[i];
}
function done () {
if (lines.length == arrayOfFeedUrls.length) {
console.log(lines.length);
}
}
You may also want to look into promises, an alternative programming style to callbacks, which aims to avoid callback hell.
Have to admit that I'm very new to node.js and struggling to grok the callback stuff. In my limited experience, adding one more parameter to the callback function may be the trick. The hard question is, which parameter?
In your example, if the function scrape had an extra boolean "lastOne", then it could call console.log(lines) itself. Or, if it understood that a null url meant to stop. However, I don't think even this works, as I'm not sure everything will get done in order. If the 2nd URL takes forever, the last one may complete first, right??? (You could try it). In other words, I still don't know which parameter to add. Sorry...
What seems more reliable is to set a counter to urls.length, and for scrape() to decrement it each time. When the counter reaches 0, it knows that the entire process is done and it should log (or do whatever) with the result. I'm not 100% sure where to declare this counter. Coming from Java I still have little idea what is a static global, what is an instance, whatever...
Now, a true-blue node.jser would pass a function to doWhatever as an extra parameter to scrape(), so that you can do something other than console.log(). :-) But I'd settle for the check for zero.
to elaborate slightly, add a callWhenDone parameter to scrape(), and add (somewhere in all that nesting!!!)
if (--counter <= 0)
callWhenDone (lines);
Ok, so here's how i've solved the problem, feel free to comment and tell me if it's right.
var lines = [];
var arrayOfFeedUrls = [url1,url2,...];
function scrape(array){
var url = array.shift();
http.get(url, function(res) {
res.pipe(new FeedParser([options]))
.on('readable', function () {
var stream = this, item;
while (item=stream.read()) {
line = item.title;
lines.push(line);
}
}).on('end', function () {
if(array.length){
scrapeFeeds(array);
}
});
});
});
scrapeFeeds(array);
Thanks for all the answers, i'm looking more in depth to async as I've got more complicated stuff to do. Let me know what you think of my code, it's always useful.

Categories