Is there a way to implement context on async function? - javascript

I'm writing a NodeJS based backend (cloud-function), and I got trouble in the situation as follow:
const context = createContext()
async main(event){
// I need to cache something here
context.set("I need this")
await someDeepFunction()
}
async function someDeepFunction() {
// ...... and got it in a very-very-deep logic
const val = context.get()
}
The main problem is that it's an async function, and when the NodeJS is handling the next request whiling waiting for the last, the context should switch automatically to ensure never lack the cache data of the first request.
I found a javascript project https://github.com/ealush/context, but it's not able to create context when use async.
Is it possible to implement and how?

Related

AWS SSM getparameters make behavior node js sync

Is there any way to make AWS SSM getparameters sync?
Requirement :
The secret key, id stored in the SSM store should be accessible on the server up.
Using Node and express in the backend as a reverse proxy, so we have a constant.js file, it stores all the API URLs, paths, etc.
constats.js file
const api1url = 'http://example.com/path1'
const api1_secretkey = 'secret_key'
..................
module.export = {api1url,api1_secretkey}
So we wanted to call the ssm stuff in here before setting the const variables
const SSM = require('aws-sdk/clients/ssm');
const ssm = new SSM();
const params = {
Names: ['/secret_key_api_1', '/secret_key_api_2'],
WithDecryption: true,
};
const parameterList = await ssm.getParameters(params).promise();
I understand that await cant be without async, I just wanted to convey what I am expecting, without it being an async call or whether it be in the callback of getparameters.
const api1url = 'http://example.com/path1'
const api1_secretkey = parameterList.Parameter[1].Value
But since it is an async call we are not able to wait for it,tried doing it in a separate async function and then returning the data but since the function is still async having difficulties.
Not exactly issue wrt to an async function, the async function works as expected, but I want it to be synced, the AWS get parameter function is async. because of this I am not able to do something like const api1_secretkey = process.env.secret_key , this value will be obtained when js file is executed line by line. but since i am waiting for the secret key to come from async func by the time the line by line occurs const api1_secretkey = parameterList.Parameter[1].Value , the promise is still not resolved so undefined will sit. Even if i make a .then on the get params i can make this const api1_secretkey = parameterList.Parameter[1].Value after promise resolved. but since the export module is already done the other file carries undefined in the secret key even after it is changed on promise resolve.

top-level-await error when using NextJS API

I'm building an api with NextJS and MongoDB. I do a basic setup on the top of the API file:
const { db } = await connectToDatabase();
const scheduled = db.collection('scheduled');
and I continue the code with my handler function:
export default async function handler(req, res) {
otherFunctionCalls()
...
}
const otherFunctionCalls = async () => {
...
}
I know await will work only within an async function, but I would like to use the scheduled constant in other functions what the handler calls, that's why I need to call it on the top.
If I put the constant to every single function, then it's code duplication.
What's the best practice to access to scheduled constant? Should I add the otherFunctionCalls declaration into the handler function?
The complete error what I got:
Module parse failed: The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)
File was processed with these loaders:
* ./node_modules/next/dist/build/babel/loader/index.js
You may need an additional loader to handle the result of these loaders.
Error: The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)
In the comments you've said you want to find another solution rather than enabling the top-level await experiment in the tool you're using.
To do that, you'll have to adjust the module code to handle the fact that you don't have the scheduled collection yet, you just have a promise of it. If the only exported function is handler and all of the other functions are going to be called from handler, they it makes sense to handle that (no pun!) in handler, along these lines:
// A promise for the `scheduled` collection
const pScheduled = connectToDatabase().then(db => db.collection("scheduled"));
export default async function handler(req, res) {
const scheduled = await pScheduled;
await otherFunctionCalls(scheduled);
// ...
}
const otherFunctionCalls = async (scheduled) => {
// ...use `scheduled` here...
};
There are lots of ways you might tweak that, but fundamentally you'll want to get the promise (just once is fine) and await it to get its fulfillment value anywhere you need its fulfillment value. (For the avoidance of double: await doesn't re-run anything; if the promise is already fulfilled, it just gives you back the fulfillment value the promise already has.)

Will Firebase functions wait for anonymous promise to complete before closing the instance?

In Tips & Tricks the docs say
Note: If a Node.js background function returns a Promise, Cloud Functions ensures that the Promise is settled before terminating.
My question is, does this ensurance extend to anonymous callbacks that are returned from a non-promised method?
export const mutateData = functions.https.onCall(async (data, context)=>{
const data = await getAndMutateData();
await Promise.all([
furtherMutate(data.data1),
furtherMutate(data.data2),
furtherMutate(data.data3)
]);
const addendum = {
addedData1: foo,
addedData2: bar,
addedData3: foobar
};
// Not awaited, we want to do this in the background while the client gets the status back
data.writeCallback(addendum);
return "success";
}
async function getAndMutateData(){
let [data1, data2, data3] = await Promise.all([firestoreGetter1(), firestoreGetter2(), firestoreGetter3()]);
mutate(data1);
mutate(data2);
mutate(data3);
return {
data1: data1,
data2: data2,
data3: data3,
writeCallback: async function(addendum): Promise<any>{
return Promise.all([
firestoreSetter1(data1, addendum.addedData1), // Merges data streams
firestoreSetter2(data2, addendum.addedData2),
firestoreSetter3(data3, addendum.addedData3)
]);
}
}
}
Will the cloud instance close before the writeCallback has had a chance to finish? I want to give the client the success/fail status without waiting for the firestore writes to complete. There are other failsafes in place for that case.
Firstly, the tip you cite applies only to background functions. The callable function you show here is not a background function. HTTP and callables are synchronous with the client that invokes them.
Will the cloud instance close before the writeCallback has had a chance to finish?
Yes, it will. You will need to await it if you want the function to complete before the function shuts down forcibly. You can't leave async work "dangling" when the function terminates, otherwise it might have strange behavior, or simply not work at all.
For callable functions, you are obliged to return a promise that becomes fulfilled with the data to send to the client, only after all the async work is complete. If you are trying to allow some work to continue after the client receives its response, you should refer to these:
Continue execution after sending response (Cloud Functions for Firebase)
Call cloud functions without waiting for response
The most common way of continue work after sending a response is to write a pubsub function to perform the extra work, then send a message to it from the main function.

A specific confusion on writing an async function. Can anyone validate?

I am very new to NodeJS. I was trying to get a function written that can simply return a configuration value from DB. I might need to call it multiple times.
In PHP or other synchronous languages, I would use the following code for it
function getConfigValue($configKeyName)
{
// DB READ OPERATIONS
return $confguration_value_fetched_from_db
}
getConfigValue("key1");
getConfigValue("key2");
etc
But in NodeJS, I found it too difficult to do this operation because of the Asynchronous nature of the code. After asking some questions here, and after spending hours to learn Callbacks, Promises, Async/await keywords, being a beginner the below is best code I could reach.
// Below function defines the 'get' function
var get = async (key) => {
var result = await COLLECTIONNAME.findOne({key}); //MongoDB in backend
return result.value;
}
// Here I am forced to define another async function so that I can await for the get function.
function async anotherfunction()
{
var value_I_am_lookingfor1 = await get("key1");
var value_I_am_lookingfor2 = await get("key2");
}
anotherfunction();
While it might work, I am not fully happy with the result, mainly because I really don't want to do all my further coding based on the fetched value within this function anotherfunction(). All I want is to fetch a single value? Also I might need to easily call it from many places within the application, not just from here (I was planning to place it in a module)
Any better or easier methods? Or should I always get the value I want, and then nest it with a 'then.' to do the subsequent operation? I even doubt the fundamental approach I take on NodeJS coding itself may be wrong.
Can anyone guide me?
mainly because I really don't want to do all my further coding based on the fetched value within this function anotherfunction(). All I want is to fetch a single value?
Because the request is asynchronous, and your code depends on having the fetched values first, there's no option other than to wait for the values to be retrieved before continuing. Somewhere in the script, control flow needs to halt until the values are retrieved before other parts of the script continue.
Also I might need to easily call it from many places within the application, not just from here (I was planning to place it in a module)
You should have that module make the requests and export a Promise that resolves to the values needed. Rather than using await (which forces requests to be processed in serial), you should probably use Promise.all, which will allow multiple requests to be sent out at once. For example:
valuegetter.js
const get = key => COLLECTIONNAME.findOne({ key }).then(res => res.value);
export default Promise.all([
get('key1'),
get('key2')
]);
main.js
import prom from './valuegetter.js';
prom.then(([val1, val2]) => {
// do stuff with val1 and val2
})
.catch((err) => {
// handle errors
});
If other modules need val1 and val2, call them from main.js with the values they need.

What is different between asyncData and methods in nuxt js?

I currently used
asyncData for getting api data , but it can only used in pages ( not in components) .
But method can used in page and component .
These two method work the same ways and , so I am thinking to use methods for getting api data .
So I wonder is there any significant between asyncData and method ?
export default {
async asyncData ({ req }) {
let { data } = await axios.get(process.env.API_SERVER + `/v1/projects`)
return { items: data }
},
data () {
return {
items: null
}
},
methods: {
async getItems () {
let { data } = await axios.get(process.env.API_SERVER + `/v1/projects`)
this.items = data
}
}
There is a very big difference:
asyncData is a method which gets automatically called before the component gets initialized and therefore before the component data gets set.
Therefore you won't have access to this like in your methods.
asyncData is important for server side rendering where you want to fetch first your data before your component gets rendered with the fetched data. Nuxt will wait until the data got fetched before initializing and then rendering the component. Otherwise it would be rendered empty.
Methods are first available when the component is initialized.
You'll find more about asyncData here in the docs and there it's good described.
its like automatic promise
once you (ajax) request something then you get promise so you add then handler so when you get data your then code will be executed.
so ajax request will take some time so we are making that flow as async means continue the flow but when data received i need to execute some code which i have provided in then function
same goes with asyncData(its just wrapper for data with async capabilities) and async method what ever code you write inside will await for the given operation then when that operation is finished method will be executed.
its just like alert('hello') which await user for to click ok then continue the flow.
as well in server-side rendering it work same it will stop execution flow for a while for incoming data then again resumes it.
it more on depth with this js generators answer (if you are more interested): Difference between async/await and ES6 yield with generators

Categories

Resources