Hello after setup a simple async function with promise return i'd like to use then promise instead of try!
But is returning
await is a reserved word
for the second await in the function.
i've tried to place async return promise the data! but did not worked either
async infiniteNotification(page = 1) {
let page = this.state.page;
console.log("^^^^^", page);
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch(`/notifications?page=${page}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
params: { page }
})
.then(data => data.json())
.then(data => {
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch("/notifications/mark_as_read", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
body: JSON.stringify({
notification: {
read: true
}
})
}).then(response => {
this.props.changeNotifications();
});
})
.catch(err => {
console.log(err);
});
}
> await is a reserved word (100:25)
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
^
fetch("/notifications/mark_as_read", {
You should refactor how you make your requests. I would have a common function to handle setting up the request and everything.
const makeRequest = async (url, options, auth_token) => {
try {
// Default options and request method
if (!options) options = {}
options.method = options.method || 'GET'
// always pass a body through, handle the payload here
if (options.body && (options.method === 'POST' || options.method === 'PUT')) {
options.body = JSON.stringify(options.body)
} else if (options.body) {
url = appendQueryString(url, options.body)
delete options.body
}
// setup headers
if (!options.headers) options.headers = {}
const headers = new Headers()
for(const key of Object.keys(options.headers)) {
headers.append(key, (options.headers as any)[key])
}
if (auth_token) {
headers.append('Access', auth_token)
}
headers.append('Accept', 'application/json')
headers.append('Content-Type', 'application/json')
options.headers = headers
const response = await fetch(url, options as any)
const json = await response.json()
if (!response.ok) {
throw json
}
return json
} catch (e) {
console.error(e)
throw e
}
}
appendQueryString is a little helper util to do the get qs params in the url
const appendQueryString = (urlPath, params) => {
const searchParams = new URLSearchParams()
for (const key of Object.keys(params)) {
searchParams.append(key, params[key])
}
return `${urlPath}?${searchParams.toString()}`
}
Now, to get to how you update your code, you'll notice things become less verbose and more extensive.
async infiniteNotification(page = 1) {
try {
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
const data = await makeRequest(
`/notifications`,
{ body: { page } },
auth_token
)
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
const markedAsReadResponse = makeRequest(
"/notifications/mark_as_read",
{
method: "POST",
body: {
notification: { read: true }
},
auth_token
)
this.props.changeNotifications();
} catch (e) {
// TODO handle your errors
}
}
Related
I'm new to JavaScript and I'm trying make a Github API Gateway for IFTTT(cause it can't modify header) with JS on Cloudflare Worker. Here's the code:
async function handleRequest(request) {
var url = new URL(request.url)
var apiUrl = 'https://api.github.com' + url.pathname
var basicHeaders = {
'User-Agent': 'cloudflare',
'Accept': 'application/vnd.github.v3+json'
}
const { headers } = request
const contentType = headers.get('content-type')
const contentTypeUsed = !(!contentType)
if (request.method == 'POST' && contentTypeUsed) {
if (contentType.includes('application/json')) {
var body = await request.json()
if ('additionHeaders' in body) {
var additionHeaders = body.additionHeaders
delete body.additionHeaders
}
var apiRequest = {
'headers': JSON.stringify(Object.assign(basicHeaders,additionHeaders)),
'body': JSON.stringify(body),
}
} else {
return new Response('Error: Content-Type must be json', {status: 403})
}
const newRequest = new Request(apiUrl, new Request(request, apiRequest))
try {
var response = await fetch(newRequest)
return response
} catch (e) {
return new Response(JSON.stringify({error: e.message}), {status: 500})
}
} else {
var apiRequest = {
'headers': JSON.stringify(basicHeaders)
}
const newRequest = new Request(apiUrl, new Request(request, apiRequest))
var response = await fetch(newRequest)
return response
}
}
addEventListener('fetch', async (event) => {
event.respondWith(handleRequest(event.request))
})
And I got this error when I tried to run it:
Uncaught (in promise)
TypeError: Incorrect type for the 'headers' field on 'RequestInitializerDict': the provided value is not of type 'variant'.
at worker.js:1:1245
at worker.js:1:1705
Uncaught (in response)
TypeError: Incorrect type for the 'headers' field on 'RequestInitializerDict': the provided value is not of type 'variant'.
This is an older version which run well but with less flexibility:
async function handleRequest(request) {
var url = new URL(request.url)
var apiUrl = 'https://api.github.com' + url.pathname
var accessToken = 'token '
var apiRequest = {
headers: {
'User-Agent': 'cloudflare',
'Accept': 'application/vnd.github.v3+json'
}
}
const { headers } = request
const contentType = headers.get('content-type')
const contentTypeUsed = !(!contentType)
if (request.method == 'POST' && contentTypeUsed) {
if (contentType.includes('application/json')) {
var body = await request.json()
if ('token' in body) {
accessToken += body.token
delete body.token
}
var apiRequest = {
headers: {
'Authorization': accessToken,
'User-Agent': 'cloudflare',
'Accept': 'application/vnd.github.v3+json'
},
body: JSON.stringify(body),
}
} else {
return new Response('Error: Content-Type must be json', {status: 403})
}
const newRequest = new Request(apiUrl, new Request(request, apiRequest))
try {
var response = await fetch(newRequest)
return response
} catch (e) {
return new Response(JSON.stringify({error: e.message}), {status: 500})
}
} else {
const newRequest = new Request(apiUrl, new Request(request, apiRequest))
var response = await fetch(newRequest)
return response
}
}
addEventListener('fetch', async (event) => {
event.respondWith(handleRequest(event.request))
})
The only difference seems to be apiRequest, but I don't know how to fix it. I tried to claim the variable with var apiRequest = new Object() first but didn't work.
Fix with this:
let apiRequest = new Object
apiRequest.headers = Object.assign(basicHeaders, additionHeaders)
apiRequest.body = JSON.stringify(body)
And the apiRequest will look like this:
{headers:{},body:"{}"}
This seems like what RequestInitializerDict want.
Why i got output "\"userName\"" and not as "userName" ?
in my example i try to do an get api that attach to it some data and that data comes from the async-storage.
when i console the output so its shows the data like that :
"\"userName\""
but it should output "userName" .
what is the way to fix that issue ?
so what is wrong in my way ?
const getSaveUserTokenData = async (data) => {
const url =
'https://URL/userName,userToken,PlatformType,DeviceID?' +
'userName=' +
data.userName +
'&userToken=' +
data.googlToken +
'&PlatformType=' +
data.platformId +
'&DeviceID=' +
data.deviceId;
await fetch(
url,
{
method: 'GET',
headers: {
Authorization: data.azureToken,
},
}
)
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
};
You can write this way as well:
fetchFunction = async () => {
let data = {
userName: 'jon',
userToken: 'bee22',
PlatformType: 'os-ios',
DeviceID: '222222'
}
const url = `https://yoururl.com/?userName=${encodeURIComponent(data.userName)}&userToken=${encodeURIComponent(data.userToken)}&PlatformType=${encodeURIComponent(data.PlatformType)}&DeviceID=${encodeURIComponent(data.DeviceID)}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
const json = await response.json();
console.log(json);
}
If your variable names are the one you want in your url, try this:
const getData = async () => {
let userName = 'jon';
let userToken = 'bee22';
let PlatformType = 'os-ios';
let DeviceID = '222222';
const queryString = Object.entries({
userName,
userToken,
PlatformType,
DeviceID,
})
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
const response = await fetch(
'https://url...?' + queryString
);
};
};
Note: user token should not be in the url but usually in the headers of your request, like so:
fetch(someUrl, {
headers: {
Authorization: userToken
}
});
fetch(`https://yoururl.com/${userName}`,
{ method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default'
})
.then(function(response) {
//your code here
});
A more generic solution would be something like this:
async function get(route, ...params) {
const url = `${route}${params.map(p => `/${p}`)}`;
const response = await fetch(url, { method: "GET", headers });
if (!response.ok)
throw new Error(`Http error status: ${response.status}`);
return response.json();
}
by using ...params you can pass a generic amount of parameters that will then be combined with:
const url = `${route}${params.map(p => `/${p}`)}`;
In your case you would call the method like this:
const result = await get("https://url..", "jon", "bee22", "os-ios", "222222");
I have a form code that the api is a PUT method, I have a part where I have to send it in the form of a objects, but when I send it it sends it to me as an array, they also tell me that I have to send them if it is true or false
handleSubmit = async (event) => {
const {
state,
city,
mild_symptoms = [],
} = event
const YES = "Si"
console.log(event)
try {
const myHeaders = new Headers();
const url =
"XXXXXXXXX";
myHeaders.append(
"x-api-key",
"XXXXX"
);
myHeaders.append("state", state);
myHeaders.append("city", city);
myHeaders.append(
"mild_symptoms",
`{"flu_syndrome": ${mild_symptoms.includes("flu_syndrome")}, "conjunctivitis": ${mild_symptoms.includes("conjunctivitis")}, "muscle_pain": ${mild_symptoms.includes("muscle_pain")}}`
);
var requestOptions = {
method: "PUT",
headers: myHeaders,
mode: "cors"
};
const response = await fetch(url, requestOptions);
console.log("FIRST RESPONSE ", response);
const result = await response.text();
console.log("RESULT", result);
Modal.success({
title: "Éxito",
content: "Datos enviados correctamente",
onOk: ()=>{
window.location.href = "https://covid19.gob.sv/orientaciones-tecnicas/"
}
})
} catch (error) {
console.log("ERROR", error);
}
I have to send this as a objects and not as an array
"mild_symptoms",
`{"flu_syndrome": ${mild_symptoms.includes("flu_syndrome")}, "conjunctivitis": ${mild_symptoms.includes("conjunctivitis")}, "muscle_pain": ${mild_symptoms.includes("muscle_pain")}}`
);
when user wants to to POST somthing he must be singed in(without username & pass).
Problem is i'm trying to make when CreatePost() invoked it will call SingUser() and based on SingUser() fetch request it will call CreatePost() again to let user post after he sign in.
this is in createpost component
CreatePost(){
fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)
}).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status =='inactive'){
//SignUser
}else{
//post
}
}).catch((error)=>{ //later
});
}
here is SingUser() in other file
async function SignUser() {
try{
User.vtoken = await AsyncStorage.getItem('vtoken');
var userTemp={
vtoken: User.vtoken,
ntoken : User.ntoken
}
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=> response.json()).
then((responseJson)=>{
if(responseJson.path == 2){
Save(responseJson, userTemp);}
else return;
}).catch((error)=>{
});
}catch(error){}
}
async function Save(result , userTemp){
try{
await AsyncStorage.setItem('vtoken', result.vtoken);
User.vtoken = result.vtoken;
userTemp.vtoken = result.vtoken;
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=>response.json()).
then((responseJson)=>{
return 'done';
}).catch((error)=>{})
}
catch(error){}
}
export {SignUser}
i hope u understand what im trying to do if there is better way to do it thnx:(
You can do something like this:
const errorCodeMap = {
USER_INACTIVE: 10,
}
const statusMap = {
INACTIVE: `inactive`
}
const METHOD = `POST`
const APPLICATION_JSON = `application/json`
const headerDefault = {
Accept: APPLICATION_JSON,
'Content-Type': APPLICATION_JSON,
}
const who = `post`
async function createPost(payload, options) {
try {
const {
url = ``,
fetchOptions = {
method: METHOD,
headers: headerDefault,
},
} = options
const {
post,
} = payload
const response = await fetch(url, {
...fetchOptions,
body: JSON.stringify(post)
})
const {
status,
someUsefulData,
} = await response.json()
if (status === statusMap.INACTIVE) {
return {
data: null,
errors: [{
type: who,
code: errorCodeMap.USER_INACTIVE,
message: `User inactive`
}]
}
} else {
const data = someNormalizeFunction(someUsefulData)
return {
data,
errors: [],
}
}
} catch (err) {
}
}
async function createPostRepeatOnInactive(payload, options) {
try {
const {
repeat = 1,
} = options
let index = repeat
while (index--) {
const { data, errors } = createPost(payload, options)
if (errors.length) {
await signUser()
} else {
return {
data,
errors,
}
}
}
} catch (err) {
}
}
solve it, I did little adjustments
async CreatePost(){
try{
var response = await fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)});
var responseJson = await response.json();
if(responseJson.status =='inactive' && postRepeat == true){
postRepeat == false;
await SignUser();
this.CreatePost();
}
else{
//posted
}
}catch(err){}
}
I have a conditional fetch that determines a part of a URL for a subsequent fetch, but I only want it to run in certain conditions.
The following is not waiting and runs the try right away:
async function fetchURLs() {
let sessionWait = false;
if ((check1 === true) && (check2 === false))
{sessionWait = await getURL();
} else {sessionWait = true}
if (sessionWait === true){
try {
var [a, b, c] = await Promise.all([
fetch(dataUrl, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'post',
}).then((response) => response.text()).catch(error => console.log(error.message)),
fetch(settingsUrl).then((response) => response.text()).catch(error => console.log(error.message))
} catch (error) {
console.log(error);
}
});
}
async function getURL(){
let subDomain = 'a';
fetchAdd = "https://" + subDomain + ".dexcom.com/ShareWebServices/Services/General/LoginPublisherAccountByName"
await fetch(fetchAdd, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then((res) => res.json()).then((SessionData) => dataUrl = "https://" + SessionData).catch(error => console.log(error.message));
return true;
}
const tasks = getTaskArray();
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain.then(chainResults =>
currentTask.then(currentResult =>
[ ...chainResults, currentResult ] )
);
}, Promise.resolve([])).then(arrayOfResults => {
// Do something with all results
});
This Link might help you.
https://decembersoft.com/posts/promises-in-serial-with-
array-reduce/