How i can call function inside function - javascript

I would like to call a function that is inside another function, that function will clear the timeout.
I have tried the following code, but without success:
async function Blast2() {
const delayTime = 1000;
const timer = (ms) => new Promise((res) => setTimeout(res, ms));
function ClearDelayTime() {
return clearTimeout(blast);
}
const blast = setTimeout(function () {
let blast =
"SELECT * FROM admin_contacts,temporary WHERE blast_status = 'sended'";
db.query(blast, async function (err, result, field) {
if (err) throw err;
loop: {
for (var i = 0; i < result.length; i++) {
console.log(result[i].telefone);
await timer(delayTime); // then the created Promise can be awaited
}
}
});
}, delayTime);
}
// I Want Call the function ClearDelayTime() inside Blast2()
Blast2().ClearDelayTime();

I've refactored your code. It now immediately returns a function that can be used to abort.
const db = {
query: (sql, callback) => callback(undefined,
[{telefone:1},{telefone:2},{telefone:3},{telefone:4},{telefone:5}])
}
function blast2() {
const delayTime = 1000
const timer = ms => new Promise(res => setTimeout(res, ms))
let sql = "SELECT * FROM admin_contacts,temporary WHERE blast_status = 'sended'";
let abort = false;
db.query(sql, (err, result) => {
if (!err) {
(async () => {
for(let i=0; i<result.length && !abort; i++) {
console.log(result[i].telefone);
await timer(delayTime);
}
})();
}
})
return () => abort = true;
}
let abortFunc = blast2();
setTimeout(abortFunc, 2500);

Your function Blast2 doesn't return anything. If you want to call a function inside it, you could return and store it using a variable, then call it.
Something like this:
const f1 = () => {
console.log('f1 called')
const f2 = () => {
console.log('f2 called')
}
return f2
}
const returnedFunction = f1()
console.log(returnedFunction())

Related

How to write await() for multiple promises in JavaScript?

I m trying to write await for multiple promises, instead of nested functions.
Please take a look at the below code i tried, as it will explain better than me.
var main = async () => {
// const main_ = await Promise.all(fun1,fun2,fun3);
// Fun 3
const fun3 = () =>
new Promise((resolve) => async () => {
// console.log(1);
return resolve(await fun2(1));
});
// Fun 2
const fun2 = (value) =>
new Promise((resolve) => async (value) => {
value = value + 1;
// console.log(value);
return resolve(await fun1(value));
});
// Fun 1
const fun1 = () =>
new Promise((resolve) => (value) => {
value = value + 1;
// console.log(value);
return resolve(value);
});
fun3();
};
main();
I tried console logging to debut but I m getting nothing in the console.
Any help is greatly appreciated.
the syntax is wrong, its not new Promise((resolve) => async () => {}) with 2 arrow, but new Promise((resolve) => {}) also you can call promise function without await
var main = async () => {
// const main_ = await Promise.all(fun1,fun2,fun3);
// Fun 3
const fun3 = () => new Promise(resolve => {
//console.log(1);
return resolve(fun2(1));
});
// Fun 2
const fun2 = (value) => new Promise(resolve => {
value = value + 1;
//console.log(value);
return resolve(fun1(value));
});
// Fun 1
const fun1 = (value) => new Promise(async (resolve) => {
value = value + 1;
console.log('sleep 3 seconds');
await new Promise(r => setTimeout(r, 3000));
console.log(value);
return resolve(value);
});
fun3();
};
main();
If you want to call await inside a Promise callback, you can do this:
const p = new Promise((resolve) => {
(async () => {
const res = await anotherPromise();
resolve(res);
})();
});
So with this in mind, you can rewrite your functions like this:
var main = async () => {
// const main_ = await Promise.all(fun1,fun2,fun3);
// Fun 3
const fun3 = () =>
new Promise((resolve) => {
(async () => {
resolve(await fun2(1));
})();
});
// Fun 2
const fun2 = (value) =>
new Promise((resolve) => {
value = value + 1;
(async () => {
resolve(await fun1(value));
})();
});
// Fun 1
const fun1 = (value) =>
new Promise((resolve) => {
value = value + 1;
(async () => {
resolve(value);
})();
});
return await fun3();
};
// ans: 3
console.log(await main());
If you want to do it in pure async/await, you may do this:
const main = async () => {
const fun1 = async (value) => value + 1;
const fun2 = async (value) => await fun1(value + 1);
const fun3 = async () => await fun2(1);
return await fun3();
}
// output: 3
console.log(await main());
I hope this example works for you.
console.clear();
function wait(ms, data) {
return new Promise( resolve => setTimeout(resolve.bind(this, data), ms) );
}
/**
* These will be run in series, because we call
* a function and immediately wait for each result,
* so this will finish in 1s.
*/
async function series() {
return {
result1: await wait(500, 'seriesTask1'),
result2: await wait(500, 'seriesTask2'),
}
}
/**
* While here we call the functions first,
* then wait for the result later, so
* this will finish in 500ms.
*/
async function parallel() {
const task1 = wait(500, 'parallelTask1');
const task2 = wait(500, 'parallelTask2');
return {
result1: await task1,
result2: await task2,
}
}
async function taskRunner(fn, label) {
const startTime = performance.now();
console.log(`Task ${label} starting...`);
let result = await fn();
console.log(`Task ${label} finished in ${ Number.parseInt(performance.now() - startTime) } miliseconds with,`, result);
}
void taskRunner(series, 'series');
void taskRunner(parallel, 'parallel');
fun3() is an async function so you have to put await before the call.
var main = async () => {
// Fun 3
const fun3 = () => new Promise(resolve => {
//console.log(1);
return resolve(fun2(1));
});
// Fun 2
const fun2 = (value) => new Promise(resolve => {
value = value + 1;
//console.log(value);
return resolve(fun1(value));
});
// Fun 1
const fun1 = (value) => new Promise(async (resolve) => {
value = value + 1;
console.log('sleep 3 seconds');
await new Promise(r => setTimeout(r, 3000));
console.log(value);
return resolve(value);
});
await fun3();
};
main();

Function calls from data.map are not executed synchronously

I am trying to call same function from map. Depending upon number of entries function will be called.
Here is my code
getDetails = (inputData) => {
const data = {
accountName: "test",
};
let url = `/rest/jarvis/reports/v1/getData`;
let thisdata = this;
post(url, data)
.then((response) => {
if (
response.data &&
response.data.sb &&
response.data.sb.length > 0
) {
this.props.bs.betDetails = {
data: [...response.data.sportsbookBets],
exportAccesses: response.data.exportAccesses,
};
this.props.bs.betDetails.data.map((value, index) => {
console.log("Index Value --->", index);
this.getEventDetails(value, index);
}),
this.updateReducer({
...this.props.bs,
});
}
}
}
getEventDetails = async (value, index) => {
let _this = this;
let myPromise = new Promise(function (myResolve, myReject) {
console.log("Index Value at the entry--->", index);
const data = {
accountName: "test",
};
let url = `/rest/jarvis/reports/v1/getBetEventData`;
post(url, data).then((response) => {
if (response.data) {
console.log("Index Value inside--->", index);
_this.eventIdIndexMap.set(
list.eventId != null
? list.eventId
: _this.props.bs.betEventRequest.EventId,
index
);
_this.props.bs.testEventDetails[
_this.eventIdIndexMap.get(
list.eventId != null
? list.eventId
: _this.props.bs.betEventRequest.EventId
)
] = _this.props.bs.betEventResponse;
}}}
await myPromise;
}
Here problem I am facing is inside post call of 'getEventDetails' index values are not getting in sequence.
I have used promise await and async but it is not working.
Can someone please tell me how to get it properly ?
map calls its callback function without await. You can use asynchronous functions in the callback function but they won't be executed in order.
But you can create your own map with await:
async function map(array, cb) {
const result = [];
for (const element of array) {
result.push(await cb(element));
}
return result;
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
(async () => {
console.log(await map([3, 2, 1], async el => { await sleep(el * 100); return 2 * el; }));
})();
or create your own Array.prototype.syncMap:
Array.prototype.syncMap = async function(cb) {
const result = [];
for (const element of this) {
result.push(await cb(element));
}
return result;
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
(async () => {
console.log(await [3, 2, 1].syncMap(async el => { await sleep(el * 100); return 2 * el; }));
})();
It looks like you don't even need a result. You can write your own Array.prototype.syncForEach:
Array.prototype.syncForEach = async function(cb) {
for (const element of this) {
await cb(element);
}
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
[3, 2, 1].syncForEach(async el => { await sleep(el * 100); console.log(2 * el); });
[30, 20, 10].forEach(async el => { await sleep(el * 10); console.log(2 * el); });
As you can see in the output the functions in syncForEach are executed in order and the functions in forEach are executed out of order.

Create a Promise that resolves when variable is not undefined

I'm trying to Create a Promise that resolves when variable is not undefined.
Code example
https://codesandbox.io/s/quizzical-feynman-ktvox?file=/src/index.js
let fetchedPromise = new Promise((resolve, reject) => {
const check = ()=>{
setTimeout(() =>{
console.log("checking")
if (dataFetched) resolve(dataFetched);
else check()
}, 100);
}
check()
});
const waitForDataFromAnotherComponent = async () => {
let result = await fetchedPromise;
console.log("Result: ", result);
};
const assignData = () => {
setTimeout(() => {
dataFetched = 1000;
console.log(dataFetched);
}, 5000)
};
waitForDataFromAnotherComponent();
assignData();
This works but I find it inefficient as it's callstack prone and seems wrong.
Other non-working solutions I've tried:
//-------------SOLUTION 1
let fetchedPromise = new Promise((resolve, reject) => {
const check = ()=>{
if (dataFetched) resolve(dataFetched);
else check()
}
check()
});
//--------------------SOLUTION 2
let fetchedPromise = new Promise((resolve, reject) => {
if (dataFetched) resolve(dataFetched);
});
Scenario
I need a function like solution 3 that doesn't rely on setTimeout
Solved by using Javascript Proxy
Basically I assign a Proxy Object to dataFetched that listens to changes.
I re-create the function of listening due to the fact that it must include resolve()
let dataFetched
let x = {
aListener: function (val) {},
set a(val) {
dataFetched = val;
this.aListener(val);
},
get a() {
return dataFetched;
},
registerListener: function (listener) {
this.aListener = listener;
}
};
let fetchedPromise = new Promise((resolve, reject) => {
x.registerListener(function (val) {
console.log("yeyyyyyyyyyyyyyyy");
if (dataFetched) resolve(dataFetched);
});
});
const waitForDataFromAnotherComponent = async () => {
let result = await fetchedPromise;
console.log("Result: ", result);
};
const assignData = async () => {
await new Promise((resolve, reject) =>
setTimeout(() => {
x.a = 1000;
console.log(dataFetched);
resolve(dataFetched);
}, 1000)
);
};
waitForDataFromAnotherComponent();
assignData();
EDIT
Actually it's possible to externalize the resolve() function of the promise but with some downsides as stated here
example
let dataFetched
var promiseResolve, promiseReject;
let x = {
aListener: function (val) {
if (dataFetched) promiseResolve(dataFetched);
},
set a(val) {
dataFetched = val;
this.aListener(val);
},
get a() {
return dataFetched;
},
registerListener: function (listener) {
this.aListener = listener;
}
};
let fetchedPromise = new Promise((resolve, reject) => {
promiseResolve = resolve;
promiseReject = reject;
});

Unable to syncronize the functions

I'm trying to execute the functions one by one in synchronization.
var subtasks = ['Site', 'Draw', 'Material', 'Conduction', 'Cable', 'Install', 'Foundation']
function clickMe() {
return new Promise(resolve => {
jQuery("#addtoptasksubmit").trigger("click"); // triggering the button click
resolve("done click");
});
}
function typeWord(word) {
return new Promise(resolve => {
jQuery("#todotask").val(word); // input
resolve("done type");
});
}
function createSubTask() {
return new Promise(res => {
jQuery('#todotask').focus();
res("done")
})
};
function startLoop(i) {
new Promise(resolve => {
var promise = createSubTask();
promise.then(resolve => {
var typePromise = typeWord(subtasks[i]);
typePromise.then((resolve) => {
var clickPromise = clickMe();
clickPromise.then((resolve) => {
console.log(resolve);
});
});
});
})
}
let i = 0;
let prom = startLoop(i);
prom.then((res) => {
startLoop(i++);
})
code is not working properly and also I wanted to increment i automatically. For loop is a no show.
I've tried for loop and recursive async function on chrome.
Doesn't your startLoop(i) function need a return statement for the new Promise() call? I have to imagine this:
// prom = undefined as startLoop never returns anything
let prom = startLoop(i);
Change your code like so:
// Current code from description
function startLoop(i) {
new Promise(resolve => {
// Fixed code
function startLoop(i) {
return new Promise(resolve => {
var subtasks = ['Site', 'Draw', 'Material', 'Conduction', 'Cable', 'Install', 'Foundation'];
function clickMe() {
return new Promise(resolve => {
setTimeout(() => {
jQuery("#addtoptasksubmit").trigger("click");
resolve("done click");
}, 1000);
});
}
function typeWord(word) {
return new Promise(resolve => {
jQuery("#todotask").val(word);
resolve("done type");
});
}
function createSubTask() {
return new Promise(res => {
jQuery('#todotask').focus();
res("done");
})
};
function startLoop(i) {
return new Promise(res => {
var promise = createSubTask();
promise.then(
(resolve) => {
var typePromise = typeWord(subtasks[i]);
typePromise.then((resolve) => {
console.trace(resolve);
var clickPromise = clickMe();
clickPromise.then((resolve) => {
console.trace(resolve);
res("done loop " + subtasks[i]);
});
});
}
);
})
}
var _index_ = 0;
var _how_ = setInterval(() => {
if (_index_ < subtasks.length) {
let loopPromise = startLoop(_index_);
loopPromise.then((resolve) => {
_index_ += 1;
});
} else {
console.log("all done go get the new task");
clearInterval(_how_);
}
}, 10000);
I can optimise it further....

trouble with a while loop

Im trying to use a while loop with my util() function (its commented out at the bottom of the code). When I try to run the program, I am stuck in an endless loop where i dont get farther than where I'm console logging out "getProjects running"
const axios = require("axios");
const _ = require("lodash");
axios.defaults.headers.common["Private-Token"] = "iTookMyPrivateKeyOut";
const user = "yshuman1";
let projectArray = [];
let reposExist = true;
async function getProjects() {
console.log("getProjects running");
await axios
.get(`https://gitlab.com/api/v4/users/${user}/projects`)
.then(function(response) {
const arr = _.map(response.data, "id").forEach(repo => {
projectArray.push(repo);
});
console.log(projectArray);
});
}
function deleteRepo(projectArray) {
console.log("array size", projectArray.length);
const arr = _.map(projectArray).forEach(item => {
axios
.delete(`https://gitlab.com/api/v4/projects/${item}`)
.then(() => {
console.log("deleted project ID: ", item);
})
.catch(error => {
console.log(error);
});
});
}
function util() {
getProjects()
.then(() => {
if (projectArray.length == 0) {
reposExist = false;
}
if (projectArray.length < 20) {
console.log("array is less than 20");
reposExist = false;
}
deleteRepo(projectArray);
})
.catch(error => {
console.log(error);
});
}
// while (reposExist) {
// util();
// }
The while loop is synchronous, while everything in any .then (or promise await) will be asynchronous. The initial thread will never terminate. Your code will simply queue up unlimited calls of getProjects which will only console.log.
The simple solution would be to figure out how often you want to call util (once a second? once every 5 seconds?) and await a Promise that resolves after that amount of time on each iteration.
let reposExist = true;
function util() {
console.log('running');
}
const resolveAfter5 = () => new Promise(res => setTimeout(res, 5000));
(async () => {
while (reposExist) {
util();
await resolveAfter5();
}
})();

Categories