Javascript make function wait for another function before continuing - javascript

Hi I have this function that I have written.
GetIndex method
getIndex(req: connreq){
var found = false;
var number =0;
this.firereq.child(req.recipient).once('value', function(snapshot) {
if (!snapshot.exists()) {
console.log('Not exists');
this.x = '0';
}
});
}
And I call it, in this function.
SendCommand method
async sendcommand(req: connreq, cmd: string) {
this.getIndex(req);
var promise = new Promise((resolve, reject) => {
this.firereq
.child(req.recipient)
.child(this.x) .set({
sender: req.sender,
Command: cmd,
})
.then(() => {
resolve({ success: true });
})
.catch(err => {
resolve(err);
});
});
return promise;
}
However it seems that the second function continues before the getIndex method has completed. I assume we can use awaits and promises to force the sendcommand function to wait for the Getindex to finish before proceeding to the rest of it's tasks. Any assistance would be appreciated

Return a promise in the getIndex() method and execute the second in a then call back. So generally, the getIndex should be:
getIndex(req: connreq){
return new Promise((resolve,reject) =>
{
var found = false;
var number =0;
this.firereq.child(req.recipient).once('value',
function(snapshot) {
if (!snapshot.exists()) {
console.log('Not exists');
this.x = '0';
reject('Not exists');
}
resolve('exists');
});
});
}
The above will trigger the catch block if not found and the then block if found so generally it should be:
this.getIndex(req)
.then(() => {
this.firereq
.child(req.recipient)
.child(this.x) .set({
sender: req.sender,
Command: cmd,
})
.then(() => {
resolve({ success: true });
})
.catch(err => {
resolve(err);
})
})
.catch(err => {
resolve(err);
});

In the first function do the following:
getIndex(req: connreq){
return new Promise((resolve, reject) =>
let found = false;
let number =0;
this.firereq.child(req.recipient).once('value', function(snapshot) {
if (!snapshot.exists()) {
reject("not exists");
console.log('Not exists');
this.x = '0';
}
else{
resolve(snapshot.val());
}
});
});
}
Then you can do:
async sendcommand(req: connreq, cmd: string) {
this.getIndex(req).then((data)=>
{
var promise = new Promise((resolve, reject) => {
this.firereq
.child(req.recipient)
.child(this.x) .set({
sender: req.sender,
Command: cmd,
})
.then(() => {
resolve({ success: true });
})
.catch(err => {
resolve(err);
});
});
});
return promise;
}
This way getIndex() will return a promise and everything insde then() will be executed after getIndex() returns.

Return Promise from getIndex and await it in sendCommand function
getIndex(req: connreq){
return new Promise((resolve, reject) => {
var found = false;
var number =0;
this.firereq.child(req.recipient).once('value', function(snapshot) {
if (!snapshot.exists()) {
console.log('Not exists');
this.x = '0';
}
});
resolve();
}
});
and
async sendcommand(req: connreq, cmd: string) {
await this.getIndex();
....
}

Related

JavaScript - replace setTimeout with async / await

First, I know this is a common question. I'm trying to get a handle on how to use async / await in place of setTimeouts, but all the examples I see online use a setTimeout to simulate the async. This throws me off when it's a set timeout that I'm trying to replace.
In the function below, I want this.filteredResultsto await the results of an API call before trying to filter those results and assign it to this.filteredResults.
getResults() {
let allResults= airtableQuery.getTable("Transfers"); // API call using imported 'getTable' function
console.log(allResults); // returns full array ▶[] although it's not available for filtering yet.
setTimeout(() => { // I want to replace this timeout
this.filteredResults = allResults.filter(
(result) => result.fields.User === "dev"
);
}, 250); // random ms that is roughly how long airtableQuery takes for the API call.
},
And the airtableQuery:
getTable(table) {
let recordsArr = [];
base(`${table}`)
.select({
maxRecords: 8000,
})
.eachPage(
function page(records, fetchNextPage) {
records.forEach((record) => {
recordsArr.push(record);
});
fetchNextPage();
},
function done(err) {
if (err) {
this.$toasted.error(err);
}
}
);
return recordsArr;
},
Please make the outer function an async function and then await the results before filtering them.
async function getResults() {
let allResults = await airtableQuery.getTable("Transfers");
this.filteredResults = allResults.filter(
(result) => result.fields.User === "dev"
);
},
Given that getTable() is not a Promise, await will not do anything. For that reason, we can make getTable() return a Promise which will resolve with recordsArr.
getTable(table) {
return new Promise((resolve, reject) => {
let recordsArr = [];
base(`${table}`)
.select({
maxRecords: 8000,
})
.eachPage(
function page(records, fetchNextPage) {
records.forEach((record) => {
recordsArr.push(record);
});
fetchNextPage();
},
function done(err) {
if (err) {
this.$toasted.error(err);
reject(err)
}else {
resolve(recordsArr)
}
}
);
})
}
Hope it helps.
i always likes primise,this my code show you
getTable(table) {
return new Promise((res, rej) => {
let recordsArr = [];
base(`${table}`)
.select({
maxRecords: 8000,
})
.eachPage(
function page(records, fetchNextPage) {
records.forEach((record) => {
recordsArr.push(record);
});
fetchNextPage();
res(recordsArr)
},
function done(err) {
if (err) {
this.$toasted.error(err);
rej(err)
}
}
);
})
}
getResults() {
airtableQuery.getTable("Transfers").then(res => {
let allResults = res
console.log(allResults);
this.filteredResults = allResults.filter(
(result) => result.fields.User === "dev"
);
});
}

issue with async await

I am trying to make two block of code to run sequentially with async and await
I have the code in stackblitz, open the console on Chrome to see the trace
let isMomHappy = true;
function willIgotNewPhone () {
return new Promise( (resolve, reject) => {
if (isMomHappy) {
const phone = {
brand: 'samsung',
color : 'black'
};
resolve(phone);
} else {
const reason = new Error('mom not happy');
reject(reason);
}
});
}
async function showOff(phone) {
return new Promise( (resolve, reject) => {
const message = ' Hey Friend I show my phone ' + phone.brand;
resolve(message);
});
}
async function askMom() {
return await new Promise( async (resolve) => {
console.log('before asking Mom'); // log before
await willIgotNewPhone()
.then( function(fullfilled) {
console.log('Got phone from mom ' + JSON.stringify(fullfilled));
})
.catch( function(error) {
console.log(error.message);
});
console.log('after asking Mom'); // afeter log
resolve('END');
});
}
let data: any[] = [];
async function createData() {
return new Promise( (resolve, reject) => {
for (let index = 0; index < 500000; index++) {
const element: any = {};
element.id = index;
element.name = '' + index;
data.push(element);
}
if (data && data.length > 0) {
console.log(' ====== creating data size=%s', data.length);
resolve(data);
} else {
reject( new Error(' ==== Creating data Error : empty'));
}
});
}
async function callCreateData() {
return new Promise( async (resolve) => {
console.log(' ======before creating data');
await createData().then( (dataReturn: any[]) => {
console.log(' ----datareturn length=%s', dataReturn.length);
});
console.log(' ======after creating data');
});
}
async function callingMom() {
await askMom().then( (str) => {
console.log(str);
});
}
callingMom();
callCreateData();
I am calling 2 functions this.callingMom() and this.callCreateData();
and expecting the traces of the 2 functions to be sequential
I was expecting the following output
before asking Mom
Got phone from mom {"brand":"samsung","color":"black"}
after asking Mom
=====before creating creating data
===== creating data size=500000
----datareturn length=500000
===== after creating creating data
but I got the output :
before asking Mom
======before creating data
====== creating data size=500000
Got phone from mom {"brand":"samsung","color":"black"}
----datareturn length=500000
======after creating data
after asking Mom
END
Any idea what is my problem ?
Thanks
async functions can be used for two things, primarilly: to return a Promise, and to be able to use the await keyword inside. If you're not using await, or if the only await you're using is the Promise that's going to be returned, there's no point in having an async function at all - just use a normal function that returns a Promise, like in your willIgotNewPhone.
Also, in order to chain promises together, you need to use then. Simply calling asynchronous functions right after the other won't cause the thread to pause until they're done. Like this:
callingMom().then(callCreateData);
let isMomHappy = true;
function willIgotNewPhone() {
return new Promise((resolve, reject) => {
if (isMomHappy) {
const phone = {
brand: 'samsung',
color: 'black'
};
resolve(phone);
} else {
const reason = new Error('mom not happy');
reject(reason);
}
});
}
function showOff(phone) {
return new Promise((resolve, reject) => {
const message = ' Hey Friend I show my phone ' + phone.brand;
resolve(message);
});
}
function askMom() {
return new Promise(async (resolve) => {
console.log('before asking Mom'); // log before
await willIgotNewPhone()
.then(function(fullfilled) {
console.log('Got phone from mom ' + JSON.stringify(fullfilled));
})
.catch(function(error) {
console.log(error.message);
});
console.log('after asking Mom'); // afeter log
resolve('END');
});
}
let data = [];
function createData() {
return new Promise((resolve, reject) => {
for (let index = 0; index < 500000; index++) {
const element = {};
element.id = index;
element.name = '' + index;
data.push(element);
}
if (data && data.length > 0) {
console.log(' ====== creating data size=%s', data.length);
resolve(data);
} else {
reject(new Error(' ==== Creating data Error : empty'));
}
});
}
function callCreateData() {
return new Promise(async (resolve) => {
console.log(' ======before creating data');
await createData().then((dataReturn) => {
console.log(' ----datareturn length=%s', dataReturn.length);
});
console.log(' ======after creating data');
});
}
function callingMom() {
return askMom().then((str) => {
console.log(str);
});
}
callingMom().then(callCreateData);

How to .then chain but need the resolve() value from the previous promise - javascript?

The issue lies in the "backendLoginCheck" function. I want to .then() chain "ifUserIsDisabled" after "getUserByEmail". But I need the "userRecord" from getUserByEmail for the input into "ifUserIsDisabled".
I also want both functions to share the same .catch in "backendLoginCheck" function.
Current Code:
function getUserByEmail(email){
return new Promise(function(resolve, reject){
firebase.serverAuthAdmin147th.getUserByEmail(email)
.then(function(userRecord) {
resolve(userRecord);
})
.catch(function (error) {
reject({token: null, errorCode: "auth/user-not-found"});
});
})
}
function ifUserIsDisabled(userRecord){
return new Promise(function(resolve, reject){
if(!userRecord.disabled){
resolve();
}
else{
reject({token: null, errorCode: "auth/user-disabled"});
}
})
}
function backendLoginCheck(email, password, callback){
var token = null;
var errorCode = null;
var uid = null;
getUserByEmail(email)
.then(function(userRecord){
ifUserIsDisabled(userRecord);
})
.catch(function(error){
callback(error);
});
}
Desired Idea:
...
getUserByEmail(email)
.then(ifUserIsDisabled(userRecord))
.then(nextFunction())
.then(nextFunction2(uses_resolveVal_from_nextFunction))
.then(nextFunctionEtc())
.catch(function(error){
callback(error);
});
If I'm understanding you correctly, it looks like you're almost there. If a then chain in a promise returns another promise you can pass the resolved values down the chain
for example:
function firstFunction() {
return new Promise((resolve, reject) => {
if (someError) {
reject(firstErr)
} else {
resolve('first value')
}
})
}
function secondFunction() {
return new Promise((resolve, reject) => {
if (someError) {
reject(secondErr)
} else {
resolve('second value')
}
})
}
firstFunction()
.then((resolvedFirstValue) => {
return secondFunction()
})
.then((resolvedSecondValue) => {
console.log(resolvedSecondValue)
})
.catch((err) => {
// any error in the entire chain
console.error(err)
})
should be like this:
getUserByEmail(email)
.then(function(userRecord){
return ifUserIsDisabled(userRecord);
})
.then(nextFunction())

Async promise not returning result

How come I do not get a value in my res after the promise resolves?
My console.log looks something like this:
=====!!USER NOT FOUND!!=====
Res: undefined
This is my function
async function findUser(userID, userType) {
await new Promise((resolve, reject) => {
usersTable.findOne (
{ _id: userID }
,function (err, data) {
if (err) {
throw new Error('findUser: ' + err);
} else {
if (!data) {
console.log("=====!!USER NOT FOUND!!=====")
resolve("NEW");
} else {
console.log("=====USER FOUND=====")
resolve("OK");
};
};
});
})};
This is my caller
async function main() {
var res = "";
try {
// Find the user
res = await findUser(userEmail, "tenant");
console.log("Res: " + res );
if (res == "NEW") {
res = await newUser(); // Add the new tenant
}
}
catch(err) {
console.error(err);
console.log(" newBooking: " + err);
callback( { error:true, err } );
}
}
main();
find User should return sth:
async function findUser(userID, userType) {
return await new Promise((resolve, reject) => {
...
});
}
If you do await findUser() youre waiting until the async function returns sth. Your async function returns undefined.
By the way: You might not use an async function at all:
function findUser(userId,userType){
return new Promise(...);
}

How to pass parameter to a promise function

this might seem a silly question but I am a newbie in this topic. I am working on promises on node js. And I want to pass parameter to a promise function. However I could not figure it out.
someModule.someFunction.then(username, password,function(uid) {
/*stuff */
}
and the function is something like
var someFunction = new Promise(username, password, function(resolve, reject) {
/*stuff using username, password*/
if ( /* everything turned out fine */ ) {
resolve("Stuff worked!");
} else {
reject(Error("It broke"));
}
});
Wrap your Promise inside a function or it will start to do its job right away. Plus, you can pass parameters to the function:
var some_function = function (username, password) {
return new Promise(function (resolve, reject) {
/* stuff using username, password */
if (/* everything turned out fine */) {
resolve("Stuff worked!");
} else {
reject(Error("It broke"));
}
});
};
Then, use it:
some_module.some_function(username, password).then(function (uid) {
// stuff
});
 
ES6:
const some_function = (username, password) => {
return new Promise((resolve, reject) => {
/* stuff using username, password */
if (/* everything turned out fine */) {
resolve("Stuff worked!");
} else {
reject(Error("It broke"));
}
});
};
Use:
some_module.some_function(username, password).then((uid) => {
// stuff
});
Another way(Must Try):
var promise1 = new Promise(function(resolve, reject) {
resolve('Success!');
});
var extraData = 'ImExtraData';
promise1.then(function(value) {
console.log(value, extraData);
// expected output: "Success!" "ImExtraData"
}, extraData);
Even shorter
var foo = (user, pass) =>
new Promise((resolve, reject) => {
if (/* condition */) {
resolve("Fine");
} else {
reject("Error message");
}
});
foo(user, pass).then(result => {
/* process */
});
You can return your promise in a function with arguments. Like this:
function someFunction(username, password) {
return new Promise((resolve, reject) => {
// Do something with the params username and password...
if ( /* everything turned out fine */ ) {
resolve("Stuff worked!");
} else {
reject(Error("It didn't work!"));
}
});
}
someFunction(username, password)
.then((result) => {
// Do something...
})
.catch((err) => {
// Handle the error...
});
You can use .bind() to pass the param(this) to the function.
var someFunction =function(resolve, reject) {
/* get username, password*/
var username=this.username;
var password=this.password;
if ( /* everything turned out fine */ ) {
resolve("Stuff worked!");
} else {
reject(Error("It broke"));
}
}
var promise=new Promise(someFunction.bind({username:"your username",password:"your password"}));
Not sure if understand correctly but in order to send argument from promise to another function you can do something like this:
function logUser(username, password){
return new Promise((resolve, reject) => {
let response = 'user logged in'
resolve(response)
})
}
function showMessage(msg){
console.log(msg)
}
logUser('user', 'pass').then((respFromLogUser) => {
showMessage(respFromLogUser)
})
I know this is old, but this may help someone digging through google. This is a more practical example where I just pass 2 parameters to a promise function and wait for it to resolve. Hopefully this helps. The setTimeout simulates "processing time". After 3 seconds the value will be returned from the promise and printed to screen.
const addNumbers = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b);
}, 3000);
});
};
let getResult = async (a, b) => {
let value = await addNumbers(a, b);
console.log(value);
};
getResult(1, 3);
i use this..
let verifyEmail = (email) => new Promise((resolve, rejected) => {
let rsp = {isRepeated:false}
let sql = `select id from users where email='${email}' `
try{
db.query(sql, (err,result)=>{
if(!err){
if(result.length > 0){
rsp = {isRepeated:true}
}
}
})
resolve(rsp)
}catch(e){
rejected({ok:false,err:e})
}
})

Categories