Promise on change event - javascript

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.

Related

Async button in electron call an async function

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");
}
}

Promises not waiting in an synchronously implementation to chrome.storage.session.get

I am quite new to promises and I think the implementation is quite weird also ;-)
I am working on a manifest 3 extension and need to make calls to chrome.storage.session.get and chrome.storage.local.get synchronously without callback seen from the caller side.
This is because a lot of the code in the big project is used both in the extension but also on normal web pages etc and it will be a nightmare to rewrite everything and test it again.
But my implementation test with async/await does not work as expected.
I have this function
const getObjectFromSessionStorage = async function(key)
{
return new Promise((resolve, reject) =>
{
try
{
chrome.storage.session.get(key, function(value)
{
if (chrome.runtime.lastError)
reject(chrome.runtime.lastError);
if(typeof(value[key]) === 'undefined')
reject('undefined:' + key);
resolve(value[key]);
});
}
catch (ex)
{
reject(ex);
}
});
};
That I try to call synchronously in this function:
const getItemPromise = (session, key) =>
{
let returnvalue;
(async function ()
{
if(session)
{
returnvalue = await getObjectFromSessionStorage(key);
}
else
{
returnvalue = await getObjectFromLocalStorage(key);
}
}());
//debugger;
return returnvalue;
But it only work if I stop in the debugger just before "return returnvalue;"
If I do not it will return right away.
chrome.storage.session.set({'TEST': 'HELLO'}, () =>
{
if (chrome.runtime.lastError)
console.log(chrome.runtime.lastError);
chrome.storage.session.get('TEST', (value) =>
{
if (chrome.runtime.lastError)
console.log(chrome.runtime.lastError);
console.log(value);
});
console.log(getItemPromise(true, 'TEST'));
});
E.g without debugger stop console.log(value); is returned last and console.log(getItemPromise(true, 'TEST')); is returned first with undefined as result. With debugger stop console.log(getItemPromise(true, 'TEST')); is returned last and with the correct content.
I do not understand why - hope somebody can help me out here

Node.js: Any way to stop reading the file and the whole process in line-reader's eachLine function?

I have this code:
const lineReader = require('line-reader');
var truevar = false;
async function readLines(filename, processLine) {
return new Promise((resolve, reject) => {
lineReader.eachLine(filename, (line, last, callback) => {
if (!callback) throw new Error('panic');
if (truevar) {
// I wanna stop/finish the function here
} else {
processLine(line)
.then(() => last ? resolve() : callback())
.catch(reject);
};
});
})
};
And here's how I call the readLines function:
await readLines('somefile.txt', async (line) => {
await delay(1000) // 1 second
other_function(line);
});
I need to stop reading the file & finish the entire process once it gets to a certain point. I've read the line-reader docs, but found nothing. I also tried to do it the dirty way with "break;" etc but it's obviously just not gonna finish the job and be stuck (can't call it again unless I reload the program) so that's useless.
EDIT: Fixed the problem. I forgot to set the truevar back to false, in order to be able to call the function again.
Try this:
lineReader.eachLine(filename, (line, last, callback) => {
if (!callback) throw new Error('panic');
if (truevar) {
// Add to stop reading
cb(false);
} else {
processLine(line)
.then(() => last ? resolve() : callback())
.catch(reject);
};
});
Source: https://www.npmjs.com/package/line-reader
Found out why I wasn't able to call the function again. It wasn't the issue with async function not being stopped properly, I just didn't set the truevar back to false, in order to be able to call the function again.

What are ways to run a script only after another script has finished?

Lets say this is my code (just a sample I wrote up to show the idea)
var extract = require("./postextract.js");
var rescore = require("./standardaddress.js");
RunFunc();
function RunFunc() {
extract.Start();
console.log("Extraction complete");
rescore.Start();
console.log("Scoring complete");
}
And I want to not let the rescore.Start() run until the entire extract.Start() has finished. Both scripts contain a spiderweb of functions inside of them, so having a callback put directly into the Start() function is not appearing viable as the final function won't return it, and I am having a lot of trouble understanding how to use Promises. What are ways I can make this work?
These are the scripts that extract.Start() begins and ends with. OpenWriter() is gotten to through multiple other functions and streams, with the actual fileWrite.write() being in another script that's attached to this (although not needed to detect the end of run. Currently, fileWrite.on('finish') is where I want the script to be determined as done
module.exports = {
Start: function CodeFileRead() {
//this.country = countryIn;
//Read stream of thate address components
fs.createReadStream("Reference\\" + postValid.country + " ADDRESS REF DATA.csv")
//Change separator based on file
.pipe(csv({escape: null, headers: false, separator: delim}))
//Indicate start of reading
.on('resume', (data) => console.log("Reading complete postal code file..."))
//Processes lines of data into storage array for comparison
.on('data', (data) => {
postValid.addProper[data[1]] = JSON.stringify(Object.values(data)).replace(/"/g, '').split(',').join('*');
})
//End of reading file
.on('end', () => {
postValid.complete = true;
console.log("Done reading");
//Launch main script, delayed to here in order to not read ahead of this stream
ThisFunc();
});
},
extractDone
}
function OpenWriter() {
//File stream for writing the processed chunks into a new file
fileWrite = fs.createWriteStream("Processed\\" + fileName.split('.')[0] + "_processed." + fileName.split('.')[1]);
fileWrite.on('open', () => console.log("File write is open"));
fileWrite.on('finish', () => {
console.log("File write is closed");
});
}
EDIT: I do not want to simply add the next script onto the end of the previous one and forego the master file, as I don't know how long it will be and its supposed to be designed to be capable of taking additional scripts past our development period. I cannot just use a package as it stands because approval time in the company takes up to two weeks and I need this more immediately
DOUBLE EDIT: This is all my code, every script and function is all written by me, so I can make the scripts being called do what's needed
You can just wrap your function in Promise and return that.
module.exports = {
Start: function CodeFileRead() {
return new Promise((resolve, reject) => {
fs.createReadStream(
'Reference\\' + postValid.country + ' ADDRESS REF DATA.csv'
)
// .......some code...
.on('end', () => {
postValid.complete = true;
console.log('Done reading');
resolve('success');
});
});
}
};
And Run the RunFunc like this:
async function RunFunc() {
await extract.Start();
console.log("Extraction complete");
await rescore.Start();
console.log("Scoring complete");
}
//or IIFE
RunFunc().then(()=>{
console.log("All Complete");
})
Note: Also you can/should handle error by reject("some error") when some error occurs.
EDIT After knowing about TheFunc():
Making a new Event emitter will probably the easiest solution:
eventEmitter.js
const EventEmitter = require('events').EventEmitter
module.exports = new EventEmitter()
const eventEmitter = require('./eventEmitter');
module.exports = {
Start: function CodeFileRead() {
return new Promise((resolve, reject) => {
//after all of your code
eventEmitter.once('WORK_DONE', ()=>{
resolve("Done");
})
});
}
};
function OpenWriter() {
...
fileWrite.on('finish', () => {
console.log("File write is closed");
eventEmitter.emit("WORK_DONE");
});
}
And Run the RunFunc like as before.
There's no generic way to determine when everything a function call does has finished.
It might accept a callback. It might return a promise. It might not provide any kind of method to determine when it is done. It might have side effects that you could monitor by polling.
You need to read the documentation and/or source code for that particular function.
Use async/await (promises), example:
var extract = require("./postextract.js");
var rescore = require("./standardaddress.js");
RunFunc();
async function extract_start() {
try {
extract.Start()
}
catch(e){
console.log(e)
}
}
async function rescore_start() {
try {
rescore.Start()
}
catch(e){
console.log(e)
}
}
async function RunFunc() {
await extract_start();
console.log("Extraction complete");
await rescore_start();
console.log("Scoring complete");
}

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.

Categories

Resources