Await is not waiting to read data from file? - javascript

I write the following code to read the data from the file and push into array. But attachments.length is printing 0 first and then data is loaded and print.
const fs=require('fs');
const util=require('util');
const files=['t1.csv','t2.csv','t3.csv'];
async getdata(){
const read=util.promisify(fs.readFile);
let attachments = [];
async function run(file){
let data=await read(file);
attachments.push(data);
}
for(let file of files){
await run(file);
}
console.log(attachments.length);//should print 3
}
How to load the data first and then push correctly.
Edit: change the some part of code to use await. But loop break after first iteration without giving any error neither print my attchments.length .
Edit 2: problem resolved. Calling function should also need to be await. Thanks every one.

This is happening because run() should be awaited as well in this case,
see async function
One approach is using IIFE:
(async file => {
let data = await read(file);
console.log(data);
attachments.push(data);
})('/home/nadeem/Desktop/test.csv')

When you call an async function, it returns a promise that will eventually resolve with the value returned by the function (or reject with an uncaught exception thrown from within the function).
So you're trying to log the number of attachments before the run () function has finished. Here's what you need:
run('/home/nadeem/Desktop/test.csv')
.then(() => console.log(attachments.length))

Related

The File System Access API file writing gives error

When i run the following program:
JS:
async function write(){
const filehandle = window.showOpenFilePicker();
const writable = await filehandle.createWritable();
await writable.write('The file has been updated');
await writable.close();
}
HTML:
<button onclick = "write();">
write file
</button>
I get the following error:
[Violation] Avoid using document.write(). https://developers.google.com/web/updates/2016/08/removing-document-write
I clicked the link and it was no help, and i got the same error when using document.append, even though document.write was not used.
I'm still a newbie to the File System Access API, and need help. Thank you all!
Edit: i have found out that naming a function 'write' is enough to trigger the document.write detection, but even after renaming the function, i now get the error:
Uncaught (in promise) TypeError: filehandle.createWritable is not a function
The window.showOpenFilePicker() method returns a promise with an array of file handles according to the docs:
This means you should fulfill the promise (using await or chaining it with a then:
async function write(){
const filehandle = await window.showOpenFilePicker();
// rest of code...
}
Other than that, showOpenFilePicker returns an array containing the file handles. It needs to be retrieved from the array before you can create a writable. You can use array destructuring to do exactly that:
async function write(){
const [filehandle] = await window.showOpenFilePicker();
const writable = await filehandle.createWritable();
await writable.write('The file has been updated');
await writable.close();
}
And that should do the trick.

Waiting for another async function to finish before running

I have two functions that I want to run one after the other finishes. I'm using webdriver.IO so I need to wait for one function to log into the page, and then I want another function to run.
Other questions here on SOF are telling me to use a promise, however I need to use a promise, however when I wrap my functions in a promise I get the error SyntaxError: await is only valid in async function.
I have a login function
const Login = async () => {
const browser = await remote({
capabilities: {
browserName: 'chrome'
}
})
const userName = await browser.$('#username')
const password = await browser.$('#password')
await userName.setValue(process.env.NAMEUSERNAME)
await password.setValue(process.env.PASSWORD)
const loginButton = await browser.$('button[type="submit"]')
await loginButton.click()
}
Once this completes and the page loads I want to run another function.
I have gotten this to work with a setTimeout however I don't want to just have a chain of setTimeout in my application
It's hard to give you precise code without seeing where this is called from: but presuming it's inside some other function, you just have to mark that one async and use await inside it:
async theOuterFunction() {
await Login();
doTheOtherThing();
}
(If doTheOtherThing also returns a promise you could await that too - and would need to if you want to run other code inside theOuterFunction after that. But there's no need if it's the last statement inside the function.)

How can I declare a variable and assign it to dollar's current rate?

I am trying to write a website that gets an number input from the user as TRY (Turkish currency) and converts it to dollar. I want to do this with fetch() in js. Here is my code. If I write console.log(data.tr.rate) instead of rate = data.tr.rate, it prints dollar's current rate which exactly what I want, however when I write the code below it prints "undefined".
var rate;
const m_currency = fetch('http://www.floatrates.com/daily/usd.json').then(res => res.json()).then(function(data){
rate = data.tr.rate;
});
console.log(rate);
The code where you request the rates JSON is a Promise, which is asynchronous code. You should execute all your code inside the then block, anything you do outside that block, may execute earlier, so the value of the variable cannot be told.
If you want to fetch synchronously to assign to a variable, you may use an async function and await the resolution of the Promise, but async functions are Promises themselves, that you must run as the fetch function. Here's an example:
async function get_rate() {
var res = await fetch('http://www.floatrates.com/daily/usd.json');
var data = await res.json();
return data.tr.rate;
};
// works
get_rate().then((rate) => { console.log(rate); });
// doesn't work, no error but it's a promise and not a value
console.log(get_rate());
The fetch API is asynchronous, this means that the console.log will occur before your fetch sends a response back.
var rate; // First
const m_currency = fetch('http://www.floatrates.com/daily/usd.json').then(res => res.json()).then(function(data) {
rate = data.tr.rate; // Third
});
console.log(rate); // Second

Question about node-cache object changing to a resolved promise after assigning its value to a constant

I'm trying to wrap my head around Nodejs and Promises and I'm seeing a behavior I don't quite understand so I'd like to get some help from the experts :)
I have trainStations.js file that returns information and caches it using node-cache library.
async function getTrainStations(){
var stations = await knex.select()
.from('TrainStations')
stations.forEach(
item => cache.set(item['code'], item['name'])
);
knex.destroy();
return cache;
}
module.exports = {
getTrainStations
};
Then. in app.js file, I call it as:
const stations = (async () => {
let res = await stationsModule.getTrainStations();
return res;
})();
If I debug "res" it is clearly a node-cache object, I can call the get method with a key and get its value. However, when it gets assigned to stations, it does it in the form of a resolved promise, and when I debug I can see the values, but I can't figure out how to return the value of the promise and use it as I want.
So basically the question is, why "res" got a proper node-cache object, but later on when I want to use "stations" I have a resolved promise instead. And also, how do I access to the values within the resolved promise? I tried with .then() and I can print the values in a console.log but can't use them at all.
Thanks in advance for the help!
async function calls always return a promise for the result of an [asynchronous] operation. In
const stations = (async () => {
let res = await stationsModule.getTrainStations();
return res;
})();
stations is assigned the promise returned by the anonymous arrow function call const stations = (async () => {...})();
The promise will be resolved with res when the data becomes available.
It may be worth noting you can't return an asynchronous result (obtained in the future) to the same call out from the event loop that requested the operation. In that turn of the event loop the result is pending.
Once await has been used, all code using the result must be in an async function, accessed using promise handlers in ordinary code, or triggered by a timer or event fired after the data arrives.

Unable to set result of Fetch call to a variable and the Promise doesn't resolve

I have past experience with Promises and Fetch calls in Javascript but I just cant seem to figure this out.
I am trying to fetch data from a site and store a part of the header as shown below:
async function getData() {
let response = await fetch("url.....", requestOptions);
let data = await response.headers.get('set-cookie')
return data;
}
async function main()
{
const dataset = await getData();
console.log(dataset) // This here prints out the data AFTER everything has ran, makes sense as it probably waits for the promise to be resolved.
data = dataset // This does not set the value of data to dataset. It sets it to Promise <Pending>
}
main();
So from here how can I finally set the variable Data to the resolved promise? I thought the 'await getData()' would wait for the promise to be resolved before continuing, thus allowing data to be set to an actual value and not a promise.
This code is working fine for me, Seem issue with console.log
console.log() async or sync?
async function getData() {
let response = await fetch("http://localhost:8080/");
let data = await response.headers.get('content-length')
return data;
}
async function main()
{
const dataset = await getData();
console.log(dataset) // This here prints out the data AFTER everything has ran, makes sense as it probably waits for the promise to be resolved.
data = dataset // This does not set the value of data to dataset. It sets it to Promise <Pending>
console.log(data)
}
main();
You also need to await main.
I'm guessing you're doing something like this
main() //call to main
console.log(data) //call to see `global` var data set
You need to do something like this
await main()
console.log(data)
If you're calling main from top level, you may not be able to add await so you need to declare an inline async method and call it.

Categories