Async button in electron call an async function - javascript

I have an async button on my html site. When I click the button, it should call a function, which waits for a string from my Arduino and then returns the string to the other function. If the data is saved, it should display the string on the console.
Here is the code:
async function DataReceived()
{
await Port.parser.on('data',function(data){
return data;
});
}
table.send.onclick = async () =>{
let data = await DataReceived().then(()=> {
if (data != "")
{
console.log(data);
}
else
{
console.log("too late");
}
})
Normally the function should wait for DataReceived(), but it jumps directly in the if condition and sends me back too late.
What did I do wrong? I hope you can help me.

The DataReceived() function just registers the on-event, but doesn't wait for the data to occur.
You may consider moving this registration straight into the onclick function and add your logic to the function body of the Port.parser callback

Thanks to Felix King. You got me on the right way. The Port.parser.on doesn't return a promise. I had to enclose it in new Promise for it work.
a post with the answer already exist here:
async/await using serialport in node.js
My code looks now like this now:
function DataReceived()
{
return new Promise(function(resolve, reject) {
Port.parser.on('data', (data) => {
console.log (data)
resolve(data)
})
});
}
table.send.onclick = async () =>{
let data;
data = await DataReceived();
if (data != "")
{
console.log(data);
}
else
{
console.log("too late");
}
}

Related

Async Function Inside Async Function

I am trying to get Data over my API-Endpoint and want to populate my page with the data.
I know that I have to use async/await to be sure that the variable was filled. Therefore I wrote the following lines and want to know that it is possible to write an async function inside an async function. It is working but I am not sure if it is the correct way:
async function getRoom(id) {
const response = await fetch('/api/zimmer/' + id);
if (!response.ok) {
const message = `An error has occured: ${response.status}`;
throw new Error(message);
}
const rooms = await response.json();
console.log(rooms);
return rooms;
}
async function getSelectedItem() {
var e = document.getElementById("Objekt");
if (e.value > 0) {
zimmer_select.disabled = false;
var response = await getRoom(e.value);
console.log(response);
response.forEach(function(element) {
console.log(element);
});
} else {
zimmer_select.disabled = true;
}
console.log(e.value);
}
I think it is fine to use it this way actually.
If you think about, sometimes you have to use async inside async. What if you have some async function which fetches data and you have to loop over that data and await for something. If you loop it with for each you won't be able to use await, so you should put async before it. So as long it's clean and have no other way, I think it is fine to use async inside async.

Promise on change event

I'm trying to understand how Promise API works.Currently, my idea is when a switch button is pressed/clicked to log some message or do some AJAX, depends on the situation.Which is a perfect example for chaining.Unfortunately, then does not work as expected and it logs the message on page load not on change event
const userID = $(".options").data('id');
let isEnabled = $("#statusToggler").data('status');
function showStatus() {
if(isEnabled) {
$('#statusToggler').bootstrapToggle('on', true);
} else {
$('#statusToggler').bootstrapToggle('off', true);
}
}
async function toggleStatus() {
return new Promise(function (resolve, reject) {
resolve(function () {
$("#statusToggler").on('change', function () {
let status = $("#statusToggler").prop('checked');
if (status === true) {
$("#statusToggler").data('status', 1);
$('#statusToggler').bootstrapToggle('on', true);
} else {
$("#statusToggler").data('status', 0);
$('#statusToggler').bootstrapToggle('off', true);
}
})
});
});
}
async function ajaxModifyStatus() {
await toggleStatus()
.then(function () {
console.log("Do something when toggle is pressed/clicked");
});
}
showStatus();
ajaxModifyStatus();
On first scan your promise syntax looks fine. The functions are both being called at the bottom of the script which is why they're running on page load.
If you want to have them run on an event you want to give the event the function like it's an argument like ajaxModifyStatus rather than ajaxModifyStatus().
Sorry I haven't used jQuery in ages so cant remember how to write it. Here's how you might do with normal js...
let element = document.getElementById('myid')
element.addEventListener('change', ajaxModifyStatus)
// Or...
element.addEventListener('change', async() => {
let result
try {
result = await ajaxModifyStatus()
} catch (err) {
console.log(err)
}
// Do something with result...
})
As the previous comments mentioned you don't necessarily need promises for this to work unless you actually want the result of the Ajax function.
Note I've actually written this as async await syntax because it's easier on my phone. Just replace that code with the promise if you want to do it that way.

Javascript fetch multiple pages

there is url: "http:/myurl/mydata/pages/"
the task is call url+"1",url+"2",...,until there is no correspondent page, number of pages is unknown
I am not sure about design of the decision. I know I can you "async await" approach, can I avoid it? Is the next approach ok?
let url= "http:/myurl/mydata/pages/";
let finished=true;
let page=1;
let datas={};
while(!finished) {
fetch(url+page)
.then(function(data) {
collectData(page,data);
page+=1;
})
.catch(function(error) {
finished=true;
});
}
function collectData(page,data){
datas[page]=data;
}
Can I use Promises for this task?
If you want a async-await approach:
async function fetchPages(url, page) {
try{
const data = await fetch(url+page);
collectData(page+url, data);
await fetchPages(url, page + 1);
} catch(e) {
return 'Its over';
}
}
};
This looks like a job for recursion!
let url= "http:/myurl/mydata/pages/";
let page=1;
let datas={};
recurse().then(/*...*/)
function recurse() {
return new Promise(function(resolve, reject) {
fetch(url+page)
.then(function(data) {
collectData(page,data);
page+=1;
return recurse()
})
.catch(function(error) {
resolve()
});
})
}
function collectData(page,data){
datas[page]=data;
}
NOTE: I didn't test this, so might not work exactly as written. But it should set you on the right track.

Need to wait for promise result from top level code

I have to make an async call to a 3rd party API and I want the code execution to wait for the response.
async function getOrderData(orderId) {
return new Promise(function (resolve, reject) {
var service = new APIservice();
service.GetOrderData(oid, function (event) {
if (event && event.hasErrors() == false) {
resolve(event.result);
} else {
reject(null);
}
});
});
}
var order = getOrderData(orderId);
//from here the code should only resume once the var order is defined with whatever's returned from the api
This is the top level code (not async) so I cannot use await.
EDIT:
Answering some suggestions:
this.$onInit = function () {
this.order = "wrong value";
getOrderData(orderId).then(order => {
this.order = "correct value";
});
};
this function will end with "test" being "wrong value". This is what I am trying to avoid.
You can await the Promise returned by getOrderData().
However, in order to use await you need to wrap your call to getOrderData in an async function (there is no such thing as top-level await at the moment - it may one day be a thing however. At present, it can only be used when inside an async function):
// getOrderData function initializaion...
(async _ => {
var order = await getOrderData(orderId); // wait to recieve data before proceeding
// You can now write code wih `order`
})().catch(err => {
console.error(err);
});
Alternatively, you can write your code in a .then callback (which await is simply just syntactic sugar for) from the returned Promise of getOrderData() like so:
// getOrderData function initializaion...
getOrderData(orderId).then(order => {
// write code in here which relies on `order`
}).catch(err => {
console.error(err);
});;
you need something like this:
async function the_whole_thing() {
async function the_api_wrapper() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('joe!'), 10);
});
}
let result = await the_api_wrapper();
console.log(result);
}
the_whole_thing();
Note #1: I just swapped out the API you are calling with setTimeout, as it is also a function that takes a callback (similar to your case) and it also ensures stuff happen asynchronously.
Note #2: note that the async/await syntax can only be used in the body of another async function, so thats why I wrapped the whole thing, well, in the_whole_thing.

Call API untill certain response

I really struggle with async functions in Javasctipt. Here I have async function that calls api and saves the result. It is working fine but I need to make a loop now so this api is called untill certain condition is met. I understand that it needs to be done using await but I just can't figure out how exactly.
I tried setting up if statement and then doing something like "if condition is not met" setTimeout(getResults()); (repeat the call to async function).
async getResults() {
try {
const res = await axios(`https://blablabla`);
this.result = res.data.info;
} catch (error) {
alert(error);
}
}
async getResults() {
try {
let i = 100;
while(i-->=0){
const res = await axios(`https://blablabla`);
this.result = res.data.info;
if(this.result == 'some process finished')
{
return this.result;
}
//else retry
}
} catch (error) {
alert(error);
}
just use some cycle like while(true). And repeat body of cycle until your conditions are met

Categories

Resources