.then handler being invoked out of order - http

My ultimate goal is to assign a chunk of database to class based object. To do this I am utilizing promises in typescript with the help of the .then() function to chain them. However I am running into brick walls.
return(this.httpService.post(someurl, somepayload, someheaders)
.toPromise()
.then(response => response.json())
.then(MyCustomClass.function(MyObject)));
However when this code executes the .then(MyCustomClass.function(MyObject)) before it gets the response.json() which is causing issues in my program.
My question is, why are they occurring in that order and is there any way I can force them to execute in sequence?

You're calling MyCustomClass.function(MyObject), and passing the returned value to then(). What you actually want is to pass a function that, when called, will execute MyCustomClass.function(MyObject):
.then(() => {
MyCustomClass.function(MyObject);
}));

Related

Function inside Task.Run doesn't get executed

I have some slow part of my code that does a http request then waits for the answer and calls an adf pipeline so it can update a database parameter at the end. Since this took 2 minutes and my client app seemed so slow for my clients, I wrapped this call inside Task.Run() and set my logic inside. This works good but the last part, update a database parameter, doesn't get executed at all.
Task.Run(async () =>
{
await client.ExecuteAsync(request, CancellationToken.None);
await RunADFPipeline(pipeline, _config);
await _projectRepository.UpdateValue(id, "status", "unlock");
});
I found this example online and I applied it in my code. The first two awaits seem to execute correctly but the third one doesn't execute at all. If I set it outside of Task.Run(), it executes. The third part literally just calls a stored procedure
return await _context.Database.ExecuteSqlRawAsync("EXEC core.UpdateValue #ProjectId, #Name, #Value", parameters);
I also tried by adding ContinueWith() at the end of the Task.Run() but still no luck.
Task.Run(async () =>
{
await client.ExecuteAsync(request, CancellationToken.None);
await _adfHelper.RunADFPipeline(pipeline, _config);
}).ContinueWith((result) => _projectRepository.UpdateValue(id, "status", "unlock"));
All this code is inside a controller. Any thoughts and ideas on how can I achieve my goal and update this parameter after Task.Run() finishes or the functions inside finish?

Schedule a cron job with schedule expression from onRequest cloud function parameter

Keeping a cron job pub/sub function (functions.pubsub.schedule), within a cloud function (functions.https.OnRequest) and exporting it, does not execute.
A complete example is as follows:
export const sayHelloWhen = functions.https.onRequest((request, response) => {
cors(request, response, () => {
const scheduleExpression = request.body.data.scheduleExpression;
functions.logger.log(`Called sayHelloWhen with ${scheduleExpression}`);
functions.pubsub.schedule(scheduleExpression).onRun((context) => {
functions.logger.log(`Executed sayHelloWhen with ${scheduleExpression}`)
});
response.send({
status: "success",
data: `scheduled at ${scheduleExpression}`
})
})
})
The problem is pub/sub does not trigger. Other codes are executed.
I would like to have HTTP request body scheduleExpression bring into pubsub.schedule's parameter. I don't want a static schedule expression in corn job.
In client, I would like to define a schedule expression in client side as follows:
function scheduleFunction() {
const functions = getFunctions();
const sayHello = httpsCallable(functions, "sayHelloWhen");
sayHello({ scheduleExpression: "every 1 minute" }).then((result) => {
// const data = result.data;
console.log("Result:", result);
});
}
The example below works only for a static schedule expression, meaning that a cloud function itself has a fixed schedule expression:
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
console.log('This will be run every 5 minutes!');
return null;
});
It can be exported as cron job trigger and it executes.
But keeping pub/sub cron job function, within onRequest cloud function, as in the first code example, does not execute.
I think it is very interesting what you are trying to do, but I would like to point out that you are missing some steps that could cause your app not to execute the way you need it to.
First, you need to Terminate your HTTP functions
Always end an HTTP function with send(), redirect(), or end(). Otherwise, your function might continue to run and be forcibly terminated by the system. See also Sync, Async and Promises.
When you do not terminate them, you might end up in a deeper level in which the following code will not execute unless the previous code has finished. I would also like to say I have not found any application with nested functions like you are doing.
In the Sync, async, and promises page you can find a very explicative video to understand the lifecycle of your functions, and in the How promises work with functions section we have:
When you return a JavaScript promise to a function, that function keeps running until the promise is resolved or rejected. To indicate that a function has completed its work successfully, the promise should be resolved. To indicate an error, the promise should be rejected. This means you only need to handle errors that you want to.
In addition to all this, I would suggest using a separate file to Organize multiple functions for a more organized code, but this is only a suggestion not really necessary.
Finally, I am concerned about the scheduledExpression parameter, I think if none of the above works, you might want to check and share what this value is.

Calling then after a promise wrapped inside a function

I'm wrapping a promise with firebase inside a function and I would like to call it twice, and then do something once the second call is finished. Here is my code to make it easy to understand, I'm using firebase:
this.updateDB('abc');
this.updateDB('cde');
updateDB = (content) => {
firebase.database().ref('something').update(content)
}
If I called the database update just once I could use the 'then.' and the do something, but I have to call this function twice. How can I do something once both function calls finish?
I tried to research the question got more confused.
Would appreciate any guidelines
Thanks in advance
Since .update() can return a promise, you can use Promise.all() with both promises to know when they are both done:
Promise.all(this.updateDB('abc'), this.updateDB('cde')).then(() => {
console.log('both done here');
}).catch(err => {
console.log('an error in one or both updates occurred');
});
updateDB = (content) => {
// return promise
return firebase.database().ref('something').update(content);
}

Vuex - data from different modules are returned in random order when using then()

In one of my vuex modules I'm loading data 3 times step by step with 3 different API requests using then():
actions: {
loadRoamingHistory: function loadRoamingHistory(context, roamingFilter): Promise<Array<RoamingHistoryEvent>> {
return new Promise((resolve) => {
store.dispatch('network/loadNetworks').then(() => {
store.dispatch('country/loadCountries').then(() => {
providerApi.loadRoamingHistory(roamingFilter).then(data => {
// read already loaded networks and countries from store
let networks = context.rootState.network.networks;
let countries = context.rootState.country.countries;
// .. some data processing using informations from
// networks and countries request, that are not allways available at this point..
console.log('data processing');
commitSetRoamingHistoryEvents(context, data.roamingHistoryEvent);
resolve();
}).catch(err => console.log(err));
});
});
});
}
}
I also added console.log() commands to the network and country vuex setters in order to see what is executed first:
mutations: {
setNetworks: function setNetworks(state: NetworkState, networks: Array<Network>) {
console.log('networks loaded');
state.networks = networks;
},
I would expect the 3 requests to be executed one by one, but the log messages shows that sometimes it is executed in different order, for example log messages goes like this:
networks loaded
countries loaded
networks loaded
data processing
countries loaded
Notice that data processing should be last log, otherwise I cannot process the data correctly. Why it is executed in random order and what could be done in order to fix it?
first of all, I need to correct myself, dispatch is an action, it is asynchronous, so you're correct to use promises with them. (I'm used to mapping actions, so I don't see them much)
anyway, the point of promises was to alleviate the "callback hell". so if your structure is nested like this:
action
action
action
action
you're defeating the point of using a promise in the first place.
Instead the point is to chain them in a readable fashion like so
action
action
action
action
actions: {
loadRoamingHistory: function loadRoamingHistory(context, roamingFilter): Promise<Array<RoamingHistoryEvent>> {
return store.dispatch('network/loadNetworks')
.then(() => {
return store.dispatch('country/loadCountries')
})
.then(() => {
return providerApi.loadRoamingHistory(roamingFilter)
})
.then(data => {
// read already loaded networks and countries from store
let networks = context.rootState.network.networks;
let countries = context.rootState.country.countries;
// .. some data processing using informations from
// networks and countries request, that are not allways available at this point..
console.log('data processing');
return commitSetRoamingHistoryEvents(context, data.roamingHistoryEvent);
})
.catch(err => console.log(err));
}
}
note that...
- the initial promise is not defined. Because the dispatch is asynchronous, it already creates a promise, we just add additional calls to it.
- when returning a promise inside a promise, the next then() will handle it, whether it is withing this function or outside of it
- your catch at the end will log an error anywhere along the chain of promises

Redux Middleware currying

I have this question in my head, not sure if this is validate or not, below it's an example of redux middle console log out the store.
const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
I can see it's using currying, so in redux is calling as logger(store)(store.dispatch)(action) (Correct me if i am wrong). My question is why we currying here instead just
(store, next, action) => { // do the rest }
Thanks for any suggestion I am slowly moving into functional programming too to get my head up rhythm with it.
I think redux wants to provide three hooks to developers.
We can split the call chain logger(store)(next)(action) into
let haveStoreAndDispatch = logger(store);
let haveNext = haveStoreAndDispatch(next);
let haveAction = haveNext(action);
Then we get three hook functions.
In haveStoreAndDispatch callback function, store have been created.
In haveNext callback function, we have get the next middleware.
In HaveAction callback function, we can do something with the previous middleware's result action.
Callbacks haveStoreAndDispatch and haveNext just be called only once in applyMiddleware(...middlewares)(createStore).

Resources