how to return the value inside PromiseResult - reactjs

I will try to keep my problem as simple as possible, I have this function that I created:
get_total_by_status(status: string){
const total = imports.index(status).then((d) => {
return d.total
})
return total
}
and I'm calling this function like this:
var status_published = this.get_total_by_status("pending payment")
but it's not working, I have put a console.log(total) inside the function, and I got this:
Promise {<pending>}
[[Prototype]]:Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: 202
how can I return the 202 value??
I know that there are tons of questions similar to this one, and basically, all of them tell me to add async() at the function, and a await on the moment I call the function, I have tried this without success, and I have no idea what I'm missing here, I'm a python programer with 0 knowledge in react
Edit:
Tried this approach, still can't return the value
get_total_by_status(status: string, onSuccess) {
imports.index(status).then(
(d) => {
onSuccess(d.total);
}
);
}
# STUFFF
const status_published = this.get_total_by_status("published",
(response) => {
return response //also tried status_published = response
})
if I place a console.log(response) I do indeed can log the 202 that I was expecting, but status_published keeps being null

There are two options.
Option 1. Wrap your get_total_by_status call in an async function and await your get_total_by_status to get resolved value as follows:
async function get_total_by_status(status) {
const total = imports.index(status).then(
(d) => {
return d.total;
}
);
return total;
}
async function getPromiseValue() {
let status_published = await get_total_by_status("My status");
console.log(status_published);
}
getPromiseValue(); // prints "My status"
Option 2. Another option would be pass callback to your get_total_by_status function as an argument and call that callback in .then() block as follows:
function get_total_by_status(status, onSuccess) {
// you don't need to store any return value in this case
imports.index(status).then(
(d) => {
onSuccess(d.total);
}
);
}
get_total_by_status("My status", (response) => {
console.log(response); // prints "My status"
});
Let me know if you have any kind of query or doubt regarding above code snippets :)

Related

How can I save a value in this React lambda function?

I have this React project template, it uses Spring for backend and a PostgreSQL database.
Here, I have the name of a caregiver, and what i want, is to get the id of that caregiver.
I don't know how to retrieve the id, from the findCaregiver method. When in the function, "result.id" will show the correct id, but when it returns to "handleSubmit", the initial method, the value is gone. I tried storing it in the current components' state, in a global variable, even in localStorage. But nothing works, after the function is done, the value is gone. Any ideas? Thank you!!
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
let c = this.findCaregiver(name);
console.log("id: " + c);
findCaregiver(name) {
return API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
console.log("Successfully found caregiver with id: " + result.id);
//result.id shows correct id here!
} else {
this.setState(({
errorStatus: status,
error: error
}));
}
});
}
getCaregiverByName is asynchronous. When you call it, the gears are set in motion, but then the function finishes immediately. Then you return to handleSubmit, and log out nothing, because it isn't done yet.
Some time later, the get finishes, and the callback function will be called. Any code that you need to run when the result is ready needs to be done in that callback, or something called by that callback.
So if we're sticking with callbacks, you can add a callback to findCaregiver:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name, (id) => {
console.log("id: " + id);
});
}
findCaregiver(name, callback) {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
callback(result.id);
}
}
}
If you perfer promises to callbacks (most people do), you can instead change your code to return a promise. Perhaps getCaregiverByName could be modified to return a promise, but if you don't have access to that code you can wrap your existing code in a promise like this:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name)
.then((c) => {
console.log("id: " + c);
});
}
findCaregiver(name) {
return new Promise((resolve, reject) => {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
resolve(result.id);
} else {
reject(error);
}
})
});
}
And if it's returning a promise, you have the option to use async/await:
asycn handleSubmit() {
let name = this.state.formControls.caregiverName.value;
const c = await this.findCaregiver(name);
console.log("id: " + c);
}

Axios Data in Array logs undefined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
Simplified:
Use Axios to get data
Place data in an array and end function with return array
The array is passed to function
console log data from the array
why is it returning undefined?
Long Story:
I am re-coding to the Single responsibility principle,
so the function calls and returns weather data,
Later on, create a single function that adds data as elements to the hmtlDom.
I need to be able to select specific variables from the API data,
I'm just learning JSON and I was sure I was doing it wrong, so I simplified the results,
I'm working in Typescript, so it might be a typing issue.
reading through documentation hasn't helped, Last Resort is here.
export function getWeatherData(api : string) {
var weatherData: any = []
axios.get(api)
.then(function (response) {
weatherData.push(response.data.city.name)
})
.catch(function(error){
console.log(error)
})
return weatherData
}
enter image description here console.log(weatherData)
function main() {
var city = getCity()
var api = getApi(city)
let weatherData = getWeatherData(api)
console.log(weatherData)
clearDivs()
addDivs(howManyReadings)
addDataToDivs(weatherData)
}
export function addDataToDivs(weatherData: any) {
// let li = document.getElementsByClassName("weatherInnerContainer")
// let nI = li.length
// for (var i = 0; i < nI; i++) {
console.log(weatherData[0])
// li[i].appendChild(weatherData['city']['name'])
// li[i].appendChild(weatherData['list'][i.toString()]['main']['temp'])
// li[i].appendChild(weatherData['list'][i.toString()]['dt_txt'])
// li[i].appendChild(weatherData['list'][i.toString()]['weather']['0']['description'])
// let nElement = document.createElement('img')
// let iconValue = (weatherData['list'][i.toString()]['weather']['0']['icon']).toString()
// let iconLink = 'https://openweathermap.org/img/wn/' + iconValue + '#2x.png'
// nElement.src = iconLink
// li[i].appendChild(nElement)
// }
}
Console returns: undefined
axios.get is asynchronous function, which happens 'at a some time', while the function you made is synchronous. This means, that execution of getWeatherData() is immediate, and it does not wait for the results of axios.get.
You can solve this by using promises or callbacks, whichever you prefer. Promise based solution would look something like this:
export function getWeatherData(api : string) {
return axios.get(api)
.then(function (response) {
return response.data.city.name
})
.catch(function(error){
console.log(error)
})
}
function main() {
var city = getCity()
var api = getApi(city)
getWeatherData(api).then(weatherData => {
console.log(weatherData)
clearDivs()
addDivs(howManyReadings)
addDataToDivs(weatherData)
}
}

reactJS fetch in a function executes but timing is off

I have a reactJS application where I am trying to validate some user input against a database value. The database is stored on AWS so I am using a fetch to a Web API that I wrote. This is the code that I am executing:
passString = "003" + newValue;
console.log("call function with ", passString);
var returnedValue = mqRequest(passString);
console.log("return from fetch with ", returnedValue);
if (returnedValue != newValue) {
localPlanID.message = "The Plan ID you entered was not found on our system";
localPlanID.css = "textbox4Bytes input-box-error";
}
The value of the variable newValue is VSTA
The code will call a function called mqRequest that is in a separate file. I include this by using this line of code:
import {mqRequest} from '../functions/commonFunctions.js';
The code of the function looks like this:
export function mqRequest (passedData) {
//var url = "https://webaccuapi-dev.accurecord-direct.com/api/homepage?mqRequest=" + passedData;
var url = "http://webaccuapi-dev.accurecord-direct.com/api/homepage?mqRequest=" + passedData;
const options = { method: 'GET' };
var returnString = "";
fetch(url, options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
if (myJson == undefined)
{
returnString = "fetch failed";
}
else
{
returnString = myJson[0].return_response;
console.log("from function, myJson[0] = ", myJson[0]);
}
});
console.log("from function, after fetch, returnString = ", returnString);
return returnString;
}
When I execute the code, this is what I see in the console.log:
call function with 003VSTA
from function, after fetch, returnString =
return from fetch with
from function, myJson[0] = {return_response: "VSTA", return_code: "0", return_plan_name: "N/A", return_menu_string: "N/A"}
So, it appears that I am calling the function and passing it 003VSTA. The function picks up this value, builds the url variable, and executes the fetch. The fetch returns myJson[0].return_response with a value of VSTA which is correct!
The problem that I am having is, I think, a timing issue. I believe the function is called but the code is continuing to execute even though the function and fetch have not finished executing. How do I get the code to wait for a value to be returned by the function before continuing?
Thanks.
The timing issue is due to the fact the fetch call is asynchronous.
To resolve your timing issue, there are a couple of approaches. A popular one is to use Promises for the job. Here's how:
First, you need to tweak the "mqRequest" function:
export function mqRequest (passedData) {
// ...
// Step 1: Instead of returning a String, return a Promise.
return new Promise((resolve, reject) => {
fetch(url, options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
if (myJson == undefined) {
returnString = "fetch failed";
} else {
returnString = myJson[0].return_response;
console.log("from function, myJson[0] = ", myJson[0]);
}
// Step 2: resolve the Promise with the String
resolve(returnString);
});
});
}
Then, call it like you would call a Promise:
passString = "003" + newValue;
console.log("call function with ", passString);
mqRequest(passString).then(function(returnedValue){
console.log("return from fetch with ", returnedValue);
if (returnedValue != newValue) {
localPlanID.message = "The Plan ID you entered was not found on our system";
localPlanID.css = "textbox4Bytes input-box-error";
}
});
This way, the mqRequest function call will wait for the returned data instead of continuing with the flow of the code without the returned data.
And now your logs should execute as expected.

Angular: What's the correct way to return Observable?

I have the following method which isn't working correct:
getProducts(): Observable<Product[]> {
let PRODUCTS: Product[];
this.http.get(this.base_url + "api/products")
.subscribe(
(data) => {
for(var i in data) {
PRODUCTS.push(new Product(data[i].id, data[i].name, data[i].category, data[i].description, data[i].price, data[i].amount));
}
},
(error) => {
console.log(error);
});
return of(PRODUCTS);
}
The error I'm getting is this:
TypeError: Cannot read property 'push' of undefined
Now, I know that the PRODUCT array is not accessable from within the subscribe function, but I cannot get the correct solution for it.
Can anyone help me with that. I want to return an Observable<Product[]>.
Thank you in advance!
Edit: Updated to account for the fact that the API seems to return an array-like object rather than a true array.
You want to use map:
getProducts(): Observable<Product[]> {
return this.http.get(this.base_url + "api/products")
.map(data => {
let products = [];
for (let i in data) {
products.push(new Product(data[i].id, data[i].name, data[i].category, data[i].description, data[i].price, data[i].amount));
}
return products;
})
.do(null, console.log);
}
Since #pixelbit's comment keeps getting upvotes despite being wrong, here's an example showing why it is wrong:
// Fakes a HTTP call which takes half a second to return
const api$ = Rx.Observable.of([1, 2, 3]).delay(500);
function getProducts() {
let products = [];
api$.subscribe(data => {
for (let i in data) {
products.push(data[i]);
}
});
return Rx.Observable.of(products);
}
// Logs '[]' instead of '[1, 2, 3]'
getProducts().subscribe(console.log);

AngularJS: promise in a loop

I am unable to do the promise looping.
I make a service call to get list of providers, then for each provider, I make another service call to get a customer.
A provider has 1 or more customers. So eventual list of customer is to be decorated and displayed.
In other format I am trying to achieve:
*serviceA.getProvider(){
foreach(providers){
foreach(provider.customerID){
serviceB.getCustomer(customerId)
}
}
}
.then(
foreach(Customer){
updateTheCustomer;
addUpdatedCustomerToAList
}
displayUpdatedCustomreList();
)*
I have written following code, that isn't working
doTheJob(model: Object) {
let A = [];
let B = [];
let fetchP = function(obj) {
obj.Service1.fetchAllP().then(function (response) {
let P = cloneDeep(response.data);
_.forEach(P, function(prov) {
_.forEach(prov.CIds, function(Id) {
A.push(Id);
});
});
_.forEach(A, function(CId) {
return obj.Service2.getById(CId);//what works is if this statement was: return obj.Service2.getById(A[0]);
//So, clearly, returning promise inside loop isn't working
});
})
.then(function(response) {
B.push(response.data); //This response is undefined
angular.forEach(B, function (value) {
obj.updateAdr(value)
});
obj.dispay(B);
});
};
fetchP(this);
}
forEach don't stop when you use return inside of it, try to use a plain loop instead, why you don't just loop with for ?
_.forEach(A, function(CId) {
return obj.Service2.getById(CId);
}
as stated by #Ze Rubeus if you return inside a callback within a for loop that value will be lost, since it's not returned to the caller.
probably you wanted something like this
return Promise.all(A.map(function(CId){
//collect each promise inside an array that will then be resolved
return obj.Service2.getById(CId);
})

Resources