How to code a "try again" in a Promise? - javascript

I will try to describe my problem as the best I can. I have a method who (1)get all Grafana datasources via the API (2)create 2 JSON (3)post them to Grafana API.
The thing is sometimes one of my JSON is not finish when the code make the 3rd step so I got an error and the result is not what I want.
updateDashboard = Meteor.bindEnvironment(function() {
console.log("called updateDashboard()");
new Promise(Meteor.bindEnvironment(function(resolve) {
// get all the datasources of Grafana
HTTP.call("GET", 'http://localhost:3000/api/datasources', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
},
function(error, result) {
if (!error) {
allDataSources = result.data;
resolve(allDataSources);
} else {
console.error(error);
}
});
})).then(function(allDataSources) {
// create the dashboard
return new Promise(function(resolve) {
//ANCHOR
var dataJSON = {
//create the dashboard
"annotations": {
"list": []
},
"description": "Containers metrics",
"editable": true,
"gnetId": null,
"graphTooltip": 1,
"hideControls": false,
"id": null,
"links": [],
"refresh": "1s",
//create the lines
"rows": _.map(allDataSources, function(ds, index) {
return newGraphOverview(ds, index);
}),
//dashboard things
"schemaVersion": 14,
"style": "dark",
"tags": [
"docker"
],
"time": {
"from": "now-15m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"1s",
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Docker Containers _custom_from_js",
"version": 1
}
dataJSONDetails = newGraphDetails(allDataSources);
resolve(dataJSON);
});
}).then(Meteor.bindEnvironment(function(dataJSON) {
// send the dashboard
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSON,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.log("result post " + dataJSON.title + " ----------------------------------")
console.log(result);
} else {
//HERE I WANT TO DO IF ERROR GO TO ANCHOR
console.log("error post " + dataJSON.title + " ----------------------------------")
console.error(error);
}
});
//send the dashboard for details view
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSONDetails,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.log("result post " + dataJSONDetails.title + " ----------------------------------")
console.log(result);
} else {
//HERE I WANT TO DO IF ERROR GO TO ANCHOR
console.log("error post " + dataJSONDetails.title + " ----------------------------------")
console.error(error);
}
});
}));
});
I know the code snipped doesn't work but it was easier for me to make it readable.
So someone could help me to make a thing like "if error try to create again" ? I have seen Meteor retries but it don't think it's what I need

You shouldn't use promises or callbacks. Write normal, synchronous-looking code as you've seen in Meteor examples.
var datasources = null;
try {
var request1 = HTTP.call("GET", 'http://localhost:3000/api/datasources', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
}
});
// From http://docs.meteor.com/api/http.html#HTTP-call
datasources = request.data;
} catch (e) {
console.error(e);
return;
}
// Do all the other steps you keep wanting to do...
Repeat a similar statement for your other HTTP calls. Generally, you will not be throwing errors unless localhost is unreachable, in which case everything is unreachable. So don't bother with try-catch. Let the exception be thrown and handled by the client (the caller of the method).
You shouldn't generally have to use Meteor.bindEnvironment.

Related

Amadeus flight booking working but Hotel Booking API doesn't

So I first integrated Amadeus for flight booking and everything went well but problem arrived when I started integrating hotel booking. If I use nodejs library of Amadeus, I get a response that my access token is invalid. This is my code of nestjs service and response.
async hotelSearch(data) {
try {
var amadeus = new Amadeus({
clientId: process.env.API_KEY,
clientSecret: process.env.API_SECRET
});
return await amadeus.shopping.hotelOffers.get(data)
} catch (error) {
return error;
}
}
And this is the response.result -
"result": {
"errors": [
{
"code": 38190,
"title": "Invalid access token",
"detail": "The access token provided in the Authorization header is invalid",
"status": 401
}
]
},
"parsed": true
},
"description": [
{
"code": 38190,
"title": "Invalid access token",
"detail": "The access token provided in the Authorization header is invalid",
"status": 401
}
],
"code": "AuthenticationError"
}
How can I get Invalid Access Token error when I am using the library for it?? Anyway, after facing this issue I decided to use axios instead but still got no success.
async getToken(): Promise<{access_token: string}> {
try {
const data = qs.stringify({
client_id: process.env.API_KEY,
client_secret: process.env.API_SECRET,
grant_type: 'client_credentials'
});
const config:AxiosRequestConfig = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://test.api.amadeus.com/v1/security/oauth2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
return await axios(config)
.then((response) => {
return((response.data));
})
.catch((error) => {
console.log(error);
});
} catch (error) {
return error;
}
}
async hotelSearch(data) {
try {
const tokenData=await this.getToken()
const refreshToken='Bearer '+ ( tokenData).access_token
console.log('token', refreshToken)
const config:AxiosRequestConfig = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-city',
data: data,
headers: {'Authorization':refreshToken},
};
return await axios(config).then((response) => {
return(JSON.stringify(response.data));
})
.catch((error) => {
return(error);
});
// var amadeus = new Amadeus({
// clientId: process.env.API_KEY,
// clientSecret: process.env.API_SECRET
// });
// return await amadeus.shopping.hotelOffers.get(data)
} catch (error) {
return error;
}
}
And this is the response I got this time.
{
"message": "Request failed with status code 400",
"name": "Error",
"stack": "Error: Request failed with status code 400\n at createError (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\core\\createError.js:16:15)\n at settle (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\core\\settle.js:17:12)\n at IncomingMessage.handleStreamEnd (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\adapters\\http.js:322:11)\n at IncomingMessage.emit (node:events:525:35)\n at endReadableNT (node:internal/streams/readable:1359:12)\n at processTicksAndRejections (node:internal/process/task_queues:82:21)",
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": null,
"headers": {
"Accept": "application/json, text/plain, */*",
"Authorization": "Bearer CMHEjXBrpzE7YxF9O7GKygCtzCxO",
"Content-Type": "application/json",
"User-Agent": "axios/0.26.1",
"Content-Length": 117
},
"method": "get",
"url": "https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-city",
"data": "{\"cityCode\":\"DEL\",\"radius\":\"5\",\"radiusUnit\":\"KM\",\"checkInDate\":\"2023-03-10\",\"checkOutDate\":\"2023-03-11\",\"adults\":\"2\"}"
},
"status": 400
}
I have cross-checked the payload. The bearer token is all good when I console it and even I checked the request with fiddler and there too header and data are getting passed. Any help to get this work through either of the method is really appreciated.
The amadeus.shopping.hotelOffers.get() endpoint has been decommissioned so you won't be able to use it. Install the latest version of the Node library and use the new Hotel Search endpoint as below:
var Amadeus = require(amadeus);
var amadeus = new Amadeus({
clientId: 'YOUR_API_KEY',
clientSecret: 'YOUR_API_SECRET'
});
// Get list of available offers in specific hotels by hotel ids
amadeus.shopping.hotelOffersSearch.get({
hotelIds: 'RTPAR001',
adults: '2'
}).then(function (response) {
console.log(response);
}).catch(function (response) {
console.error(response);
});
You can also check the migration guide for more details and how to use the new Hotel Search version.

Create an entry to a REST API with post

I'm struggling a bit within a small project for fetching and creating (via POST) an entry, where I have on one side:
A GraphQL server (apollo)
A react app, using useQuery hook
A rest API, where the resolvers of the Apollo project is fetching data with async JS functions
I have the following obstacles:
I'm not able to post an entry for the rest API via GraphQl query or Mutation.
I have success in this post request:
POST https://technologytalents.io/space-cats/index.php/openapi/create_channel_entry
Accept: application/json
Content-Type: application/x-www-form-urlencoded
User-Agent: axios/0.21.1
channel_id=1&url_title=Blas&entry_date=12345678&title=Dooom&session_id=b288ea559b20c584a3a793685ceb20c240c26569
The success response of this is:
{entry_id: 2}
In my graphQL schema:
input entryIntput {
url_title: String
title: String
channel_id: Int
entry_date: Int
}
type postEntrySuccess {
entry_id: Int
}
type Mutation {
createEntry(input: entryIntput): postEntrySuccess
}
and in the resolvers:
Mutation: {
createEntry: async (_, entry) => await channelEntriesService.postEntry(entry)
}
my ChannelEntriesSerives looks like:
const axios = require('axios')
const authenticate = require('./authenticate')
class ChannelEntries {
constructor(options) {
this._options = options
}
async getEntries() {
const auth = await authenticate.auth()
const patch = {
...options,
url: `${options.url}/get_channel_entries?channel_id=1&where[status]=open&session_id=${auth.session_id}`
}
const response = await axios(patch)
return response.data
}
async postEntry(entry = { url_title: 'Blas', title: 'Dooom', entry_date: Date.now(), channel_id: 1 }) {
const auth = await authenticate.auth()
const patch = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
url: `${this._options.url}/create_channel_entry?channel_id=${entry.channel_id}&url_title=${entry.url_title}&title=${entry.title}&entry_date=${entry.entry_date}_id=${auth.session_id}`
}
const response = await axios.request(patch)
return response.data
}
}
const options = {
method: 'GET',
url: 'https://technologytalents.io/space-cats/index.php/openapi',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}
module.exports = instance = new ChannelEntries(options)
When I try to execute the mutation on the GraphQl studio:
mutation CreateEntry($createEntryInput: entryIntput) {
createEntry(input: $createEntryInput) {
entry_id
}
}
I've got an error:
{
"errors": [
{
"message": "Request failed with status code 400",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"createEntry"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"config": {
"url": "https://technologytalents.io/space-cats/index.php/openapi/create_channel_entry?channel_id=undefined&url_title=undefined&title=undefined&entry_date=undefined_id=b3c77d7c74b0cc10de61c90f8e1a34b30e454f7a",
"method": "post",
"headers": {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "axios/0.21.1"
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
}
}
}
}
],
"data": {
"createEntry": null
}
}
What I'm doing wrong?
I found the reason for the error, and this is due to my rusty Axios basics. The config of an Axios request should have "data" property, so changing it to
const patch = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
url: `${this._options.url}/create_channel_entry`,
data: `channel_id=${entry.channel_id}&url_title=${entry.url_title}&title=${entry.title}&entry_date=${entry.entry_date}&session_id=${auth.session_id}`
}
returns the correct response.
The other issue is just a correct mapping of the response with graphql schema.

Axios POST request returned Undefined

I'm trying to build react-native fuction to make POST request to an API using Axios. The function seems to work but i keep getting the response as undefined. I've tested POST request with Postman, it works normally.
{
"CaThuHoiList": [
{
"NGAY": "20-01-2020",
"TH_ID": 33,
"CA": 1,
"CT_DONVI_ID": 78,
"CREATE_BY": 4797,
"TRANG_THAI": "HT",
"CREATE_DATE": "20-01-2020 00:00",
"KHO_ID": null,
"LOAI": "TT"
},
{
"NGAY": "20-01-2020",
"TH_ID": 34,
"CA": 1,
"CT_DONVI_ID": 78,
"CREATE_BY": 4797,
"TRANG_THAI": "BD",
"CREATE_DATE": "20-01-2020 00:00",
"KHO_ID": null,
"LOAI": "TL"
}
],
"Status": 1,
"Message": ""
}
However i couldn't get the same response (undefined) while running my function:
onPostJson = () => {
axios.post('https://10.1.127.17:11111/vpdu/get-ca-thu-hoi', {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
FromDate: "01-Jan-2020",
ToDate: "01-Feb-2020",
Ca: 1
})
})
.then(function (response) {
data = response;
console.log(data); \\Storing response in data still getting undefined
return response;
})
.catch(function (error) {
console.log(error);
});
}
Could anyone tell me what is the problem? Thanks in advance.
You need to have data pulled out. I have done the changes. You may check out.
onPostJson = () => {
let configObject = {
"url": "https://10.1.127.17:11111/vpdu/get-ca-thu-hoi",
"method": "post",
"headers": {
'Content-Type': 'application/json'
},
"data":{
"FromDate": "01-Jan-2020",
"ToDate": "01-Feb-2020",
"Ca": 1
}
}}
axios.request(configObject ).then((res) => {
console.log("react1: ", res);
console.log("react2: ", res.data);
})
}
const inserrequest=async () => {
let addreq = await axios.post('http://xxxxxx..//Employee/PostInsertrequest',
{
ReqEmpCode: 'xxxxxx',
});
console.warn(JSON.stringify(addreq.data));
}

Query Elasticsearch via Axios

I have an Elasticsearch instance that I can successfully query from Postman. I'm now trying to execute that same query from JavaScript via Axios. However, when I send my Axios request, I receive a 400 error. Currently, my request looks like this:
try {
let authorizationToken = getAuthToken();
let parameters = {
headers: {
"cache-control": "no-cache",
"Content-Type": "application/json",
"Authorization": "Basic " + authorizationToken
},
body: {
"size": 100,
"query": {
"bool": {
"filter": [
{ "range": {
"created_at": {"gte":"now-10m"}
} }
]
}
}
}
};
let url = 'https://my-cluster-address/my-index/_search?scroll=10m';
let res = await axios.post(url, parameters);
console.log('all good');
} catch (ex) {
console.log(ex);
}
What is wrong with my query? Why am I getting a 400 error?

How to re-do a code part if there is an error without rewriting it ?

In my code I make some API calls and sometimes 1 of them return an error but if I re-do it just after it works (I don't really know what's wrong maybe the JSON that I post is not finish or I don't know...)
So to make that I have coded:
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSON,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.error("result post dataJSON --------------------OK------------")
} else {
console.log("error post dataJSON --------------------KO------------")
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSON,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.error("result post dataJSON at the 2nd time --------------------OK------------")
} else {
console.log("error post dataJSON at the 2nd time --------------------KO------------")
}
});
}
But it's very ugly to make something like this I think so is it a way to recall the code's part when there is an error ?
Well, my first suggestion is to understand why the call fails the first time around and see if you can fix it.
Excluding that, it depends a bit on you plan to use the data and such, but, for example, you could isolate the HTTP call in a function, and recall the function with the same arguments.
function callAPIwithData(myData) {
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: myData
},
function(error, result) {
if (!error) {
console.error("OK: result post dataJSON")
} else {
console.log("KO: error post dataJSON")
console.log("retrying ...")
callAPIWithData(myData);
}
});
}
of course this will need a set of checks and balances so it won't get stuck re-trying to infinity in casa there's something else broken, but you get the idea.

Categories