JavaScript return promise from function - javascript

I'm trying to return data from a called function that has a promise in it. How do I get the data into the variable?
var job = fetchJob(data[k].employer);
function fetchJob(name) {
var test = 'null'
fetch(`https://${ GetParentResourceName() }/jsfour-computer:policeFetchJob`, {
method: 'POST',
body: JSON.stringify({
type: 'policeFetchJob',
data: {
'#name': name,
}
})
})
.then( response => response.json() )
.then( data => {
if ( data != 'false' && data.length > 0 ) {
return data
})
return null;
};

You can get the promise value with async/await or with Promises, bellow I do an example with this two techniques:
function fetchJob(name) {
return fetch(`https://${GetParentResourceName()}/jsfour-computer:policeFetchJob`, {
method: "POST",
body: JSON.stringify({
type: "policeFetchJob",
data: {
"#name": name,
},
}),
})
.then((response) => response.json())
.then((data) => {
if (data != "false" && data.length > 0) {
return data;
}
});
}
async function getResponseWithAsyncAwait() {
const job = await fetchJob(data[k].employer);
}
function getResponseWithPromises() {
fetchJob(data[k].employer).then((data) => {
const job = data;
});
}

Related

Add both settimeout and timeout to in the array loop

I am looping the array using bluebird map method and then using each row as a payload to my apicall function. Everything works perfectly but I want to incorporate timeout method when response from the api takes more than 10 seconds and also settimeout method to delay 2 seconds after each api call. Please let me know how can I acheive this. I am fine without using bluebird. Thanks in advance.
handleSubmit = () => {
Promise.map(this.props.data, row => {
return apiCall(api, row).then((response) => {
if(response){
console.log(response)
} else{
console.log("failed")
}
})
}, { concurrency: 1 } )
}
apiCall: (api, input ) => {
switch (process.env.NODE_ENV) {
case 'production': { // Production environment
return new Promise((resolve) => {
window.runApi(api, input, (response) => {
if (typeof response === 'string') {
const jsonResponse = JSON.parse(response);
resolve(jsonResponse);
} else {
resolve(response);
}
});
});
}
default: {
const requestBody = input;
if (input !== "") {
requestBody.username = "user";
requestBody.password = "password";
}
const requestUrl = `api`;
return fetch(requestUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
})
.then(res => res.json());
}
}
}

Async function unexpected behavior

At the moment I am working on an Electron app that is supplied with data via an API. The renderer calls a "backend function", which first gets the API key via Keytar and then executes the API call via axios.
The problem here is that Keytar always returns null/undefined, even if a similar function with the same functionality works without any problems, also because this point can only be reached if a valid API key is stored at all and this will also be queried by Keytar.
I am new to async/await-functions, maybe I didn't get something.
btw: Maybe the title doesn't fit too well, but I was a bit at a loss about this one.
(keytarService, username, baseUrl are globals)
Here is my code:
// Api-calling function
async function makeCall(method_type, url_path, data_array) {
keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}
//index_renderer.js
webContents.on('dom-ready', () => {
apiMain
.makeCall('GET', 'user/self')
.then((data) => {
console.log(data);
document.getElementById('username_text').innerText =
data.firstName + '' + data.lastName;
})
.catch((err) => console.log(err));
});
Similar function which is working:
async function isAuthenticated() {
apiKey = await keytar.getPassword(keytarService, username);
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: 'GET',
url: baseUrl + '/api/isAuthenticated',
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: {},
}).then(
(response) => {
console.log(response);
if (!response.data.authenticated) {
logout();
}
return response;
},
(error) => {
console.log(error);
logout();
return error;
}
);
}
// call of the working function in main.js
if (authProcess.isAuthenticated()) {
mainwin.loadFile('index.html');
} else {
mainwin.loadFile('login.html');
}
Thanks in advance.
You are missing important returns in MakeCall().
Try:
function makeCall(method_type, url_path, data_array) {
// return this promise to MakeCall
return keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
// return this promise to keytar.getPassword then()
return axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}

React Redux Thunk with callback to another function -- TypeError: Cannot read property 'then' of undefined

I am using react+redux.
I have a modal form with data and images and on success I need to close the modal else display error returned from redux. In the dispatch function I have 1 more callback function to store images to S3. I am returning promise from the redux-thunk but I keep getting "TypeError: Cannot read property 'then' of undefined".
Component
handleSubmit = e => {
e.preventDefault();
if(this.isFieldEmpty()){
this.setState({ message: "All fields are mandatory with at least 1 pic" });
return;
} else {
this.setState({ message: "" });
}
const data = {
name: this.state.name,
description : this.state.description,
points : this.state.points,
attributes : this.state.attributes,
images : this.state.images,
created_by: localStorage.getItem('id'),
}
this.props.createItem(data).then(() => {
this.hideModal();
})
}
const mapDispatchToProps = dispatch => {
return {
createItem: data => {
return dispatch(createItem(data))
},
};
};
Action
const saveItemImages = (images,successcb, failurecb) => {
if(images.length > 0){
const formData = new FormData();
for(var x = 0; x<images.length; x++) {
formData.append('image', images[x])
}
const token = localStorage.getItem('token');
fetch(`${backendUrl}/upload/item-images/`, {
method: "POST",
headers: {
'Authorization': `Bearer ${token}`
},
credentials: 'include',
body: formData
})
.then(res => {
if(res.status === 200){
res.json().then(resData => {
successcb(resData.imagesUrl);
});
}else{
res.json().then(resData => {
failurecb(resData.message);
})
}
})
.catch(err => {
console.log(err);
});
} else {
successcb([]);
}
}
export const createItem = data => { return (dispatch) => {
saveItemImages(data.images, imagesUrl => {
data.images = imagesUrl;
return fetch(`${backendUrl}/admin/createItem`, {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'Authorization': `Bearer ${data.token}`
},
credentials: 'include',
body: JSON.stringify(data)
})
.then(res => {
if(res.status === 200){
res.json().then(resData => {
dispatch({
type: ADMIN_CREATE_ITEM_SUCCESS,
payload: resData
})
return true;
});
}else{
console.log("Save failed");
res.json().then(resData => {
dispatch({
type: ADMIN_CREATE_ITEM_FAILED,
payload: {
message: resData.message
}
})
})
}
})
.catch(err => {
dispatch({
type: ADMIN_CREATE_ITEM_FAILED,
payload: {
message: `Internal Error -- ${err}`
}
})
});
}, failedMessage => {
let payload = {responseMessage: failedMessage}
dispatch({
type: ADMIN_CREATE_ITEM_FAILED,
payload: payload
})
});
};
};
Thanks in advance for any help
You should return a Promise to create async flow for the action like this:
export const createItem = data => dispatch => new Promise((resolve, reject) => {
// do something was a success
resolve();
// do something was a fail
reject();
});

How to handle function in javascript object?

I'm trying to fetch data inside object, but my object shows whole function. Why doesn't it show only my return statement? What's the way to handle this problem?
const fetchContacts = async () => {
try {
await axios.get(url, {
headers: {
'auth': 'asdsdfasfd'
}
}).then(resp => {
const newRows = resp && resp.data && resp.data.map(row =>
({
name: row.name,
surname: row.surname,
city: row.city,
familyNumber: async () => {
try {
const resp = await axios.get(url, {
headers: {
'auth': 'asdsdfasfd'
}
})
return resp.data.length
} catch(error) {
return error
}
},
})
)
})
} catch(error) {
return error
}
}
You are using async/await. You don't have to use the promise returned by .then. Try something like this. I haven't tested the code.
const fetchContacts = async () => {
try {
const resp = await axios.get(url, {
headers: {
'auth': 'asdsdfasfd'
}
});
const resNo = await axios.get(url2, {
headers: {
'auth': 'somethingNew-qednken'
}
});
const newRows = resp.data && resp.data.map(row =>
({
name: row.name,
surname: row.surname,
city: row.city,
familyNumber: resNo.data.length || 0
})
);
//console.log("my newRows : ", newRows);
} catch(err) {
console.log(err);
}
}

How to access the request object in a fetch then/response function

I have a JavaScript loop iterating over an array. For every item, I perform a fetch request to insert the object. If the server response indicates it is an already inserted object, I try an update operation with another fetch call.
As the requests are asynchronous, the loop sets the request object to the next insert item before I try the update operation, so I end up requesting an update for an object it's not yet inserted.
Is there any way I can access the request object used for this fetch operation, so I can use that object instead of the loop var?
I've tried with this within the promise method, but it returns a reference to the window object: console.log(this) ==> > Window http://localhost
My code:
for (var i = 0; i < expectedRows; i++) {
var row = myArray[i];
customerCode = row['customer_code'];
customerName = row['customer_name'];
customerBalance = row['customer_balance'];
// Build body call
var callBody = {
user: 'USER',
code: customerCode,
name: customerName,
balance: customerBalance
};
var fetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: JSON.stringify(callBody),
};
// Call
var epurl = baseEP + '/customer/create';
fetch(epurl, fetchOptions)
.then(response => response.json())
.then(response => {
console.log(this) // <== Window object reference
if (response.error === 0) {
console.log('insert ok');
insertRows++;
} else {
if (response.error == 2) {
console.log('insert error => update');
var updateEP = baseEP + '/customer/update';
fetch(updateEP, fetchOptions) // <== Not what you expect
.then(updResponse => updResponse.json())
.then(updResponse => {
if (updResponse.error === 0) {
console.log('update ok.')
updateRows++;
} else {
console.log('update error: ' + updResponse.msg)
errorMessages.push(updResponse.msg);
}
})
.catch(error => {
console.log('update failure');
errorMessages.push(error);
});
} else {
console.log('insert error.');
errorMessages.push(response.msg);
}
}
})
.catch(error => {
console.log('insert failure.');
errorMessages.push(error);
});
}
I need some way to access this fetch call request object to achieve something like this:
var updFetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: this.request.body, // this as a reference to this fetch's request
}
fetch(updateEP, updFetchOptions)...
:
:
Can you try this.
for (let i = 0; i < expectedRows; i++) {
let row = myArray[i];
customerCode = row['customer_code'];
customerName = row['customer_name'];
customerBalance = row['customer_balance'];
// Build body call
let callBody = {
user: 'USER',
code: customerCode,
name: customerName,
balance: customerBalance
};
let fetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: JSON.stringify(callBody),
};
// Call
let epurl = baseEP + '/customer/create';
fetch(epurl, fetchOptions)
.then(response => response.json())
.then(response => {
console.log(this) // <== Window object reference
if (response.error === 0) {
console.log('insert ok');
insertRows++;
} else {
if (response.error == 2) {
console.log('insert error => update');
let updateEP = baseEP + '/customer/update';
fetch(updateEP, fetchOptions) // <== Not what you expect
.then(updResponse => updResponse.json())
.then(updResponse => {
if (updResponse.error === 0) {
console.log('update ok.')
updateRows++;
} else {
console.log('update error: ' + updResponse.msg)
errorMessages.push(updResponse.msg);
}
})
.catch(error => {
console.log('update failure');
errorMessages.push(error);
});
} else {
console.log('insert error.');
errorMessages.push(response.msg);
}
}
})
.catch(error => {
console.log('insert failure.');
errorMessages.push(error);
});
}
Basically, defining variables with var is not a good method as it doesn't maintain its state with each iteration of loop. But using let maintains the variable state for each iteration and you can use the variable even after doing some async task like fetch in your case.
You can achieve this by explicitly creating the RequestInit-Object and wrapping your handler functions like this:
const initObject = {
method: 'POST',
something: 1234
};
fetch('/test.json', initObject)
.then(r => r.json())
.then(((initObject) => {
return json => {
console.log({json, initObject})
}
})(initObject));

Categories