calling an api inside map function In node Js - javascript

const processInboundEmailAttachment = async (files: any[]): Promise<any[]> => {
const attachments = []
await Promise.all(
files.map(async (file) => {
try {
let response = null
response = await axios.get(file.url, {
headers: {
Accept: "message/rfc2822"
},
auth: {
username: "api",
password: "api-key"
},
responseType: "stream"
})
if (response && response.data) {
response.data.pipe(concat(async data => {
try {
const mediaUrl = await uploadToFirestore(file["content-type"], data, file.name)
attachments.push({
name: file.name,
url: mediaUrl,
id : uuidv4()
})
} catch (error) {
console.log("err", error);
}
}));
}
} catch (err) {
log.error(err)
}
})
)
return attachments // from here this return initial attachments [] array
}
const uploadAttachment = async () => {
const attachment = await processInboundEmailAttachment(JSON.parse(attach))
console.log("attachment",attachment);
// I want updated pushed attachment array here but I got [] initial decalare value
}
app.get("/uploadAttachment", uploadAttachment)
In attachment console log I got [] array , It's return initial assign values of array.
It's not wait for API response and newly pushed array.
I think There Is an some issue in Promise , It's not wait for updated array , It's
return directly initialy attachment array
Thank you for Help In advnace

Looks like it is not waiting for uploadFirestore response. You can cut down your function something like below and wrap it custom promise.
const processInboundEmailAttachment = async (files: any[]): Promise<any[]> => {
const getFileUploadedResult = function(file) {
return new Promise(async (resolve, reject) => {
try {
let response = null
response = await axios.get(file.url, {
headers: {
Accept: "message/rfc2822"
},
auth: {
username: "api",
password: "api-key"
},
responseType: "stream"
})
if (response && response.data) {
response.data.pipe(concat(async data => {
try {
const mediaUrl = await uploadToFirestore(file["content-type"], data, file.name)
resolve({
name: file.name,
url: mediaUrl,
id : uuidv4()
})
} catch (error) {
reject(err)
}
}));
}
} catch (err) {
log.error(err)
reject(err)
}
})
}
return Promise.all(
files.map(async (file) => {
return getFileUploadedResult(file)
})
)
}
const uploadAttachment = async () => {
const attachment = await processInboundEmailAttachment(JSON.parse(attach))
console.log("attachment",attachment);
// I want updated pushed attachment array here but I got [] initial decalare value
}
app.get("/uploadAttachment", uploadAttachment)

Related

React Fetch Inside a function Map

I'm trying to make a request for each item captured in the MAP, but I would like to wait for the response before going to the other object within the MAP. At the moment my code is making all the requests at the same time, which ends up crashing the Backend.
function RequestComputers (Computers) {
Computers.map((e) => {
Details(e, data.region, data.apitoken).then(data => {
if(data)
setContent2((array) => [...array, data[0]])} ).catch(error => console.log(error))
})
}
const Details = async (Computer, region, token) => {
try {
const test = {'region': region, 'apitoken': token, 'product': '1', 'computer': Computer}
const response = await fetch('url', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(test)
}
)
const data = await response.json()
return data
} catch(error) {
console.log(error)
}
}
I need to wait for the fetch response and only then make another fetch request
You can use a simple for loop:
async function RequestComputers (Computers) {
for ( const computer of Computers ) {
try {
const data = await Details(computer, data.region, data.apitoken);
if ( data ) {
setContent2((array) => [...array, data[0]]);
}
} catch(error){
console.log(error);
}
}
}
Reference
I think you could use .forEach and await Details:
async function RequestComputers (Computers) {
Computer.forEach(async(computer) => {
try {
const data = await Details(computer, data.region, data.apitoken);
if ( data ) {
setContent2((array) => [...array, data[0]]);
}
} catch(error){
console.log(error);
}
})
}

Using FileTransfer plugin pass data to next request in for loop

I have a image upload Request with a param. I want to send response from 1st request to all next requests inside for loop.
Page.page.ts
//function to take Photos
takePhoto() {
this.camera.takePhoto().then((res: any) => {
res.map((v) => {
this.uploadMedia(v.fullPath, v.fullPath.split('/').pop())
})
})
}
// function to upload Photos
uploadMedia(path, type) {
this.imgLoader = true;
this.camera.uploadFileMedia(path, 'UploadImage', type, this.postId).then((res: any) => {
if (res.status == true) {
this.postId = res.data.post_id; // I want to pass this postId to All other Requests.
this.userImages.push({ img: res.data});
}
})
}
Camera Service .ts
uploadFileMedia(path: string, url: string, fileType: string, post_id): Promise<any> {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'images',
fileName: fileType,
params: {post_id: post_id }
}
return new Promise(resolve => {
fileTransfer.upload(path, url, options).then((data) => {
resolve(res)
}, (err) => {
})
})
}
Solved it by Converting my UploadFileMedia() from Promise to Observable in my camera.service.ts
UploadFileMedia(path: string, url: string, fileType: string, post_id): Observable<any> {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: "images",
fileName: fileType,
chunkedMode: false,
params: { post_id: post_id }
};
return new Observable(result => {
fileTransfer.upload(path, url, options).then((data) => {
let res = JSON.parse(data.response);
result.next(res);
}, err => {
result.error(err);
});
});
}
and inside my page.ts:
takePhoto = async () => {
this.camera.takePhoto().then(async (res: any) => {
for (let v = 0; v < res.length; v++) {
await new Promise((resolve, reject) => {
this.camera.UploadFileMedia(res[v].fullPath, 'UploadImage', res[v].fullPath.split('/').pop(), this.postId).subscribe((res: any) => {
console.log(res);
if (res.status == true) {
this.postId = res.data.post_id;
this.userImages.push({ img: res.data});
resolve(true)
} else {
reject();
}
})
})
}
})
}
Idea taken From:
Another Answer for Same Problem

How to call methods one after one?

There is a function that accepts three parameters:
function getAddressStructure(country: number, city: number, region: number) {
}
I need to create a promise that returns data for each varaible and as result returns a common object {countries: [], cities: [], regions: []}
How to do that using promise(s)?
let promise = new Promise((resolve, reject) => resolve());
If you have three different end points that are not dependent on each other then u can use this approach:
export async function handleResponse(response) {
if (response.ok) return response.json();
if (response.status === 400) {
const error = await response.text();
throw new Error(error);
}
throw new Error("Network response was not ok.");
}
export function handleError(error) {
console.error("API failed. " + error);
throw error;
}
export function GetCountries() {
const url = "/countries"
return fetch(url, {
method: "GET",
credentials: "include",
}).then(handleResponse).catch(handleError);
}
export function GetCities() {
const url = "/cities"
return fetch(url, {
method: "GET",
credentials: "include",
}).then(handleResponse).catch(handleError);
}
export function GetRegions() {
const url = "/regions"
return fetch(url, {
method: "GET",
credentials: "include",
}).then(handleResponse).catch(handleError);
}
function getAddressStructure() {
return Promise.all([
GetCountries(),
GetCities(),
GetRegions()
])
.then((response) => {
return {
countries: response[0],
cities: response[1],
regions: response[2]
};
})
.catch((error) => {
return {
countries: response[],
cities: response[],
regions: response[]
}
});
}
// this is how you can use it:
getAddressStructure()
.then((response) => {
var apiResults = { };
apiResults = { ...response};
return resolve(apiResults);
})
What you want to achieve , you can use callback function to achieve these behavior without using promise.
async function getAddressStructure(country(args, getCities,getregioR)
{
var countries = await getCountries():
var cities= await getCities ():
var regions = await getRegion ();
return { countries : countries, cities: cities, regions: regions}
}
async function getCountries ();
async function getCities() {}
async function getRegion () {}

Service call is not going in react-native. Getting warning like "Possible unhandled Promise Rejection, Reference error: response is not defined"

I am new to react native and making service call for the first time. My problem is service call is not going and getting warning like
Possible unhandled Promise Rejection, Reference error: response is not defined.
I am trying to hit loginUser function.
Api.js
const BASE_URL = "http://localhost:8200";
export const api = async (url, method, body = null, headers = {}) => {
try {
const endPoint = BASE_URL.concat(url);
const reqBody = body ? JSON.stringify(body) : null;
const fetchParams = {method, headers};
if((method === "POST" || method === "PUT") && !reqBody) {
throw new Error("Request body required");
}
if(reqBody) {
console.log("ReQBody--->"+reqBody);
fetchParams.headers["Content-type"] = "application/json";
fetchParams.body = reqBody;
}
const fetchPromise = await fetch(endPoint, fetchParams);
const timeOutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Request Timeout");
}, 3000);
});
const response = await Promise.race([fetchPromise, timeOutPromise]);
return response;
} catch (e) {
return e;
}
}
export const fetchApi = async (url, method, body, statusCode, token = null, loader = false) => {
console.log("In FetchAPi Function");
try {
const headers = {}
const result = {
token: null,
success: false,
responseBody: null
};
if(token) {
headers["securityKey"] = token;
}
const response = await api(url, method, body, headers);
console.log("fetchApi-->>"+response);
if(response.status === statusCode) {
result.success = true;
let responseBody;
const responseText = await response.text();
try {
responseBody = JSON.parse(responseText);
} catch (e) {
responseBody = responseText;
}
result.responseBody = responseBody;
return result;
}
let errorBody;
const errorText = await response.text();
try {
errorBody = JSON.parse(errorText);
} catch (e) {
errorBody = errorText;
}
result.responseBody = errorBody;
console.log("FetchApi(Result)--->>"+result);
throw result;
} catch (error) {
return error;
}
}
auth.actions.js
export const loginUser = (payload) => {
console.log("In LoginUser function2");
return async (dispatch) => {
<-----**I am not able to enter into this block**------>
try {
dispatch({
type: "LOGIN_USER_LOADING"
});
console.log("In LoginUser function3");
const response = await fetchApi("/login", "POST", payload, 200);
if(response.success) {
dispatch({
type: "LOGIN_USER_SUCCESS",
});
dispatch({
type: "AUTH_USER_SUCCESS",
token: response.token
});
dispatch({
type: "GET_USER_SUCCESS",
payload: response.responseBody
});
return response;
} else {
throw response;
}
} catch (error) {
dispatch({
type: "LOGIN_USER_FAIL",
payload: error.responseBody
});
return error;
}
}
}
In console log, I can't see anything in network tab. In the android emulator, the mentioned warning has come.
My console tab
I see that your BASE_URL is served using an http endpoint. You can only make requests to https endpoints from react native projects. A possible workaround is to use ngrok. Just download it and run ./ngrok http 8200 since your port number is 8200. It will expose an HTTPS endpoint and replace your BASE_URL with that link and try fetching the data again.
I use the following code to make API calls. See if you can integrate it in your code. it is quite simple:
In a class called FetchService:
class FetchService {
adminAuth(cb, data) {
console.log('here in the fetch service');
return fetch(
baseURL + "login",
{
method: "POST",
headers: {
Accept: "application/json",
},
body: data
}
)
.then((response) => response.json())
.then(responsej => {
cb(null, responsej);
})
.catch(error => {
cb(error, null);
});
}
}
export default FetchService;
Then call it from your component using:
import FetchService from './FetchService';
const fetcher = new FetchService;
export default class LoginScreen extends React.Component {
fetchData() {
const data = new FormData();
data.append('username',this.state.username);
data.append('password',this.state.password);
fetcher.wastereport((err, responsej) => {
if(err) {
//handle error here
} else {
//handle response here
}
}, data);
}
}

Calling Facebook Messenger API in a synchronous fashion

I'm using the Facebook Messenger API to create a very basic chatbot. I want to be able to send a series of messages in individual bubbles. However, when I call the API multiple times in the same function. I can't be sure which message will show first. How can I use async/await functionality to correctly order the messages?
Function call initially:
const getStartedProcess = async(formattedText,senderID) => {
const firstMessage = await sendTextMessage(senderID,"First message");
const secondMessage = await sendTextMessage(senderID,"Second message");
const thirdMessage = await sendTextMessage(senderID,"Third message");
}
Helpers:
const sendTextMessage = async(recipientId, messageText) => {
//format message correctly
const sent = await callSendAPI(messageData);
return 0;
}
const callSendAPI = async(messageData) =>{
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: { access_token: PAGE_ACCESS_TOKEN },
method: 'POST',
json: messageData
}, function (error, response, body) {
//Proccess
return 0;
});
}
How about this:
const sendTextMessage = (recipientId, messageText) => {
return new Promise((resolve, reject) => {
//format message correctly
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token: PAGE_ACCESS_TOKEN},
method: 'POST',
json: messageData
}, (error, response, body) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
})
}
const getStartedProcess = async(formattedText, senderID) => {
try {
const firstMessage = await sendTextMessage(senderID, 'First message');
const secondMessage = await sendTextMessage(senderID, 'Second message');
const thirdMessage = await sendTextMessage(senderID, 'Third message');
} catch (error) {
console.log(error);
}
}

Categories

Resources