I execute this function for a test in nodejs
const response = async () => {return await MyService.Adding({name})}
console.log(response)
but i get this: [AsyncFunction: response]
i want to use:
const res = await (async () => {
const response = await MyService.Adding({name})
return response
})()
console.log('RESPONDE ', res, expected)
If you are in the async function, just use await to run the other async functions.
Example
const res = await MyService.Adding({
name
})
Try:
// Just for example
const MyService = {
Adding: async (params) => params
}
async function main() {
const res = await MyService.Adding({
name: 'Your Name'
})
console.log(res)
}
main()
You are assigning a function to response
You want to eval the function in order to get the expected response.
Something like this:
let response2 = (async () => {return await MyService.Adding({name})})()
But if you are writing a small script, and you want to use await, you can't do it without an async function. So your script should be refactor to something like this:
(async () => {
const response = await MyService.Adding({name})
console.log(response);
})()
Your whole script can be written in the implicit evaluation of an async function and await will work.
It is not very preatty, but is better that managing callbacks
Related
I kind of understand the differences between callbacks, promises and async await, but I'm not quite sure how to apply this to my problem.
I stripped away a lot of the code, but basically I have an app running with an endpoint that needs to execute 3 functions (maybe I need a 4th?) and also send a "res.end()" within 3 seconds. The 3 functions are dependent on each other. Do I need to chain these functions? My main() seems completely wrong.
deleteRule() has to run and finish first
createRule() must run after deleteRule() has completed
orderRule() must run after createRule() has completed
router.post('/', function (req, res) {
async function deleteRule() {
axios.delete(DeleteURL, {auth: auth, httpsAgent: agent})
.then(response => {
let deleteRes = response.data
console.log(deleteRes)
})
}
const list = './jsons/list.json'
async function createRule() {
fs.readFile(list, 'utf-8', function(err, data) {
if (err) throw err
var thestuff = JSON.parse(data)
axios.post(CreateURL, thestuff, {auth: auth, httpsAgent: agent})
.then(response => {
let createRes = response.data
console.log(createRes)
})
})
}
async function orderRule() {
axios.put(usOrderURL, theOrder, {auth: auth, httpsAgent: agent})
.then(response => {
let orderRes = response.data
console.log(orderRes)
})
}
async function main() {
const deleteListResult = await deleteRule();
const createListResult = await createRule();
const orderListResult = await orderRule();
}
main();
// res.end must finish in 3 seconds from the initial post on the first line
res.end()
})
The then() calls return promises, but you don't do anything with them. You should either await them, or return them.
Since you declared your functions as async, make use of await in them -- that is the whole point of the async keyword:
async function deleteRule() {
let response = await axios.delete(DeleteURL, {auth: auth, httpsAgent: agent});
console.log(response.data);
return response.data;
}
Make a similar change to the other two rule-functions.
import fs from 'fs-extra'
const list = './jsons/list.json'
async function deleteRule() {
const response = await axios.delete(DeleteURL, {auth: auth, httpsAgent: agent})
const deleteRes = response.data
console.log(deleteRes)
return deleteRes
}
async function createRule() {
const data = await fs.readFile(list, 'utf-8')
const theStuff = JSON.parse(data)
const response = await axios.post(CreateURL, theStuff, {auth: auth, httpsAgent: agent})
const createRes = response.data
console.log(createRes)
return createRes
}
async function orderRule() {
const response = await axios.put(usOrderURL, theOrder, {auth: auth, httpsAgent: agent})
const orderRes = response.data
console.log(orderRes)
return orderRes
}
router.post('/', async function (req, res) {
const deleteListResult = await deleteRule();
const createListResult = await createRule();
const orderListResult = await orderRule();
// res.end must finish in 3 seconds from the initial post on the first line
res.end()
})
This is what I have:
async function myFetch() {
let loggerinfo = {
url: await "Hellothere",
token: await "212312"
};
return await loggerinfo;
}
const myfish = myFetch().then((loggerinfo) => {
return loggerinfo
})
console.log(myfish);
i am getting an "Promise { }" when I output myfish variable
I require the async and await attributes but at the same time, i need to be able to use the loggerinfo variable which "myfish" to be used outside of async and myFetch().then boxes.
my result would be like for example:
async function myFetch() {
let loggerinfo = {
url: await "Hellothere",
token: await "212312"
};
return await loggerinfo;
}
const myfish = myFetch().then((loggerinfo) => {
return loggerinfo
})
use myfish inside exports.handler
exports.handler = function (event, context) {
console.log(myfish);
};
async function myFetch() {
let loggerinfo = {
url: await "Hellothere",
token: await "212312"
};
return loggerinfo;
}
const myfish = async () => {return await myFetch();}
Use the above code to get your expected result.
use myfish inside exports.handler
exports.handler = async (event, context) {
console.log(await myfish);
}
You can use async/await in your lambda function also as mentioned above
async function myFetch() {
let loggerinfo = {
url: "Hellothere",
token: "212312"
};
return await loggerinfo;
}
(async () => {
console.log(await myFetch())
})()
I want to write a function to measure the performance of parts of code (other methods) that could return a value. This is what I came out at the moment:
const fn = async (): Promise<any> => {
setTimeout(async (): Promise<any> => {
return new Promise((resolve) => resolve('Hello World!'));
}, 3000);
};
async measure(fn: () => Promise<any>): Promise<any> {
const startTime = this.performance.now();
const result = await functionToMeasure();
const endTime = this.performance.now();
const executionTime = endTime - startTime;
console.log(`Executed in ${executionTime} ms`);
return result;
}
const result = async measure(functionToMeasure); // result is undefined
The result is that functionToMeasure actually runs but it never returns something and at the moment I can use it only with void function.
I'd like to fix it if possible, or I can change completely if there's a better way to do it.
EDIT:
Actual code
const callback = async (): Promise<any> => {
return await doSomethingAndReturn();
};
const searchResults: string[] = await measure(callback);
Do I've to wrap doSomethingAndReturn in an async Promise?
You need to wrap the setTimeout call in a promise and then resolve the result, so it should look something like this:
const {performance} = require('perf_hooks');
async function executeAndMeasure(fn) {
const startTime = performance.now();
const result = await fn();
const endTime = performance.now();
const executionTime = endTime - startTime;
console.log(`Executed in ${executionTime} ms`);
return result;
}
function someFnThatReturnsAPromise() {
return new Promise(resolve => {
setTimeout(() => {
resolve("Hello World");
}, 3000);
})
}
async function someAsyncFunction() {
return 123;
}
(async () => {
let result = await executeAndMeasure(someFnThatReturnsAPromise);
console.log(`result was ${result}`);
result = await executeAndMeasure(someAsyncFunction);
console.log(`result was ${result}`);
})();
I am trying to get a route to wait for an async function in another module to return before render runs, but no matter what I do, res.render always runs first.
This is my current code, which actually just freezes and never loads:
router.get('/', function(req, res, next) {
try {
const cities = spreadsheet.getData()
} catch(err) {
console.log(err)
}
res.render('index', { cities: cities})
})
and the function it is waiting for is this:
exports.getData = function () {
parsedData = [];
accessSpreadsheet().then(function(data) {
console.log(parsedData)
return parsedData;
});
};
const accessSpreadsheet = async() => {
await doc.useServiceAccountAuth({
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_PRIVATE_KEY,
});
const loadedDoc = await doc.loadInfo();
sheet = await doc.sheetsByIndex[0];
const cells = await sheet.loadCells(allCells[cellsIndex]);
const data = await parseData();
const moreCells = await checkNextCells()
return;
}
The render runs first, and the parsedData prints in the console. I also tried making the route async, and I tried res.render inside a callback. Is there any way to make this work?
Since accessSpreadSheet is an async function, you either need to await or return the promise (as suggested by Patrick Roberts in the comment), in getData function, and similarly in the router.
Using async await you can update your code as below (not tested)
exports.getData = async function () {
parsedData = [];
parsedData = await accessSpreadSheet();
return parsedData;
};
const accessSpreadsheet = async() => {
await doc.useServiceAccountAuth({
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_PRIVATE_KEY,
});
const loadedDoc = await doc.loadInfo();
sheet = await doc.sheetsByIndex[0];
const cells = await sheet.loadCells(allCells[cellsIndex]);
const data = await parseData();
const moreCells = await checkNextCells()
return;
}
And in the router
router.get('/', async function(req, res, next) {
let cities;
try {
cities = await spreadsheet.getData()
} catch(err) {
console.log(err)
}
res.render('index', { cities: cities})
})
In your router, spreadsheet.getData() being async, you need to handle it with async/wait, which will require your callback to be async.
router.get('/', async function(req, res, next) {
try {
const cities = await spreadsheet.getData();
res.render('index', { cities: cities}) // moved this to inside a try block
} catch(err) {
console.log(err)
// you need to handle the exception here, return error message etc
}
})
In getData, you need to return a promise that will be resolved when called in router.
exports.getData = async function () {
let parsedData = [];
try {
parsedData = await accessSpreadsheet();
} catch (exc) {
// handle exception here
}
return parsedData;
};
finally in accessSpreadsheet(), I do not see where you return the data parsed.
const accessSpreadsheet = async() => {
try{
await doc.useServiceAccountAuth({
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_PRIVATE_KEY,
});
let loadedDoc = await doc.loadInfo();
let sheet = await doc.sheetsByIndex[0];
let cells = await sheet.loadCells(allCells[cellsIndex]); // cellsIndex is not defined
let data = await parseData(); // are you to pass the sheet? do not know how parsedData() works
let moreCells = await checkNextCells()
return data; // assuming data is what is meant to be returned
} catch(exc) {
// probably return null or re-raise exception
}
}
It is important to always use try/catch or then/catch when dealing with async code in NodeJS.
Hope it sheds some light!
Goal: Get a list of files from my directory; get the SHA256 for each of those files
Error: await is only valid in async function
I'm not sure why that is the case since my function is already wrapped inside an async function.. any help is appreciated!
const hasha = require('hasha');
const getFiles = () => {
fs.readdir('PATH_TO_FILE', (err, files) => {
files.forEach(i => {
return i;
});
});
}
(async () => {
const getAllFiles = getFiles()
getAllFiles.forEach( i => {
const hash = await hasha.fromFile(i, {algorithm: 'sha256'});
return console.log(hash);
})
});
Your await isn't inside an async function because it's inside the .forEach() callback which is not declared async.
You really need to rethink how you approach this because getFiles() isn't even returning anything. Keep in mind that returning from a callback just returns from that callback, not from the parent function.
Here's what I would suggest:
const fsp = require('fs').promises;
const hasha = require('hasha');
async function getAllFiles() {
let files = await fsp.readdir('PATH_TO_FILE');
for (let file of files) {
const hash = await hasha.fromFile(i, {algorithm: 'sha256'});
console.log(hash);
}
}
getAllFiles().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});
In this new implementation:
Use const fsp = require('fs').promises to get the promises interface for the fs module.
Use await fsp.readdir() to read the files using promises
Use a for/of loop so we can properly sequence our asynchronous operations with await.
Call the function and monitor both completion and error.