IBM Cloud Function produce no output - javascript

I have some troubles while running this IBM Cloud Function:
/**
*
* main() will be run when you invoke this action
*
* #param Cloud Functions actions accept a single parameter, which must be a JSON object.
*
* #return The output of this action, which must be a JSON object.
*
*/
function main(params) {
const https = require('https');
https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
My problem is that the first invokes of this function (at least the first 3-4) produce no output. The subsequent calls run properly and the log is correctly shown. How can I fix this unpredictable behaviour? I'd like, of course, to retrieve my data at first call of this function. Thanks.

Node.js uses an non-blocking asynchronous programming model. This main function returns before the HTTP response is available.
Returning a Promise will allow you to wait on the HTTP response.
function main(params) {
return new Promise((resolve, reject) => {
const https = require('https');
https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
const explanation = JSON.parse(data).explanation
console.log(explanation);
resolve({ explanation })
});
}).on("error", (err) => {
console.log("Error: " + err.message);
reject({ error: err.message })
});
})
}

Two additional things to check:
Make sure to append .json to your endpoint
Example: https://<ibm-domain>/api/v1/web/<username>/default/<function>.json
Make sure to select Enable as Web Action in the Endpoints sidebar menu.
Also, you should be able to return an async main function in lieu of the Promise object.
async function main(params) {
try {
// some `await` function
} catch (e) {
// catch `await` errors
}
}
module.exports = main;

Related

Firebase function timeout when calling external api

I'm trying to call an external API in Firebase Functions but i always get a timeout.
What can be the issue causing this?
Here is my code
exports.getCountryData = functions.https.onRequest((request, response) => {
const https = require('https');
const options = {
hostname: "api-football-v1.p.rapidapi.com/v3",
path: '/fixtures?next=5',
headers: {
"x-rapidapi-host": "api-football-v1.p.rapidapi.com/v3",
"x-rapidapi-key": "my-api-key"
}
};
var req = https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => { data += chunk; });
resp.on('end', () => {
var result = JSON.parse(data);
console.log("Api fetched successfully");
console.log(result);
response.send({ fulfillmentText: result});
});
}).on("error", (err) => { console.log("Error: " + err.message); });
});
An event-driven function may fail to successfully complete due to errors thrown in the function code itself. Some of the reasons this might happen are as follows:
The function contains a bug and the runtime throws an exception.
The function cannot reach a service endpoint, or times out while
trying to reach the endpoint.
The function intentionally throws an exception (for example, when a
parameter fails validation).
When functions written in Node.js return a rejected promise or pass a
non-null value to a callback.
In any of the above cases, the function stops executing by default and the event is discarded. If you want to retry the function when an error occurs, you can change the default retry policy by setting the "retry on failure" property. This causes the event to be retried repeatedly for up to multiple days until the function successfully completes.
In this question, the service endpointi ‘api-football-v1.p.rapidapi.com/v3’ itself took so much time to load ( not reachable ), that was the issue. Changing the API endpoint to v3.football.api-sports.io and then calling the external API in Firebase Functions solved the issue for our user #tate_xy
It turns out using their Rapid Api url (api-football-v1.p.rapidapi.com/v3) was was resulting in a timeout. Using a direct Api url (v3.football.api-sports.io) with their domain name in it did the trick for me.
Here is my working code.
exports.getCountryData = functions.https.onRequest((request, response) => {
const https = require('https');
const options = {
hostname: "v3.football.api-sports.io",
path: '/fixtures?next=5',
headers: {
"x-rapidapi-host": "v3.football.api-sports.io",
"x-apisports-key": "my-api-key"
}
};
var req = https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => { data += chunk; });
resp.on('end', () => {
var result = JSON.parse(data);
console.log("Api fetched successfully");
console.log(result);
response.send({ fulfillmentText: result});
});
}).on("error", (err) => { console.log("Error: " + err.message); });
});

What would be a proper way of returning this promise?

I'm new to coding and Promises are somewhat of an abstract concept for me. I know that in order to return a Promise you must use .then and .catch , but I'm unsure how exactly they should be used in the following code.
/**
* Make an HTTPS request to the MTA GTFS API for a given feed.
* #param {String} baseUrl - base URL for MTA GTFS API
* #param {String} feedId - identifier for which realtime feed
* #param {String} apiKey - key for MTA GTFS API
* #return {<Object>} - Promise of parsed feed.
*/
function makeRequest(baseUrl, feedId, apiKey) {
const feedUrl = baseUrl + feedId;
return new Promise((resolve, reject) => {
const req = https.request(feedUrl,
{ headers: { 'x-api-key': apiKey } },
(res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var data;
data = [];
res.on('data', (chunk) => {
return data.push(chunk);
});
return res.on('end', function() {
var msg;
data = Buffer.concat(data);
try {
msg = nstrDecoder.decode(data);
} catch (err) {
try {
console.log(err.message);
msg = nsssDecoder.decode(data);
} catch (err) {
console.log(err.message);
msg = "";
}
}
resolve(msg);
});
}
);
req.on('error', (e) => {
reject(e.message);
});
req.end();
});
}
return console.log(makeRequest(baseUrl, feedId, apiKey));
After running this code I get a message saying the Promise is pending. Thoughts??
When calling a function that returns a promise, you're going to get the promise in a pending state being it hasn't resolve or rejected yet. You have two options.
Option one.
node 10+ you can use async await.
async function main(){
const res = await makeRequest(baseUrl, feedId, apiKey)
return res
}
Pre node 10
makeRequest(baseUrl, feedId, apiKey)
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
})
Essentially if you have to wait for the data, you have to have the code that relies on that data after the await, or in the .then block.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Your makeRequest() function returns a promise. To use that promise, you use .then() or await to get the resolved value from the promise.
Using .then():
makeRequest(baseUrl, feedId, apiKey).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
or using await:
async function someFunction() {
try {
let result = await makeRequest(baseUrl, feedId, apiKey);
console.log(result);
} catch(e) {
console.log(err);
}
}
FYI, a lot of what makeRequest() is doing can be done simpler using an http request library that already supports promises. There is a list of competent libraries to choose from here.
My favorite is got(), but you can review the list to decide which one you like. The main advantages are that they already collect the whole response for you, already support promises, support a wide variety of authentication schemes with built-in logic and can often decode or parse the response for you - all things which https.request() does not know how to do by itself.

How do I call Airtable rest API from inside an AWS Lambda?

I am trying to call my rest api endpoint in AIRTABLE from inside an AWS Lambda with no success. I get no errors, no outputs.
If I call the same code using node - it works.
I am able to use Axios in my code.
Pure airtable code (works)
var Airtable = require('airtable');
var base = new Airtable({apiKey: 'keyoMYSECRETKEY'}).base('Mybaseid');
base('MyBase').select({maxRecords: 3,view: "MyView"}).eachPage(function page(records, fetchNextPage) {
// This function (`page`) will get called for each page of records.
records.forEach(function(record) {
console.log('Retrieved',JSON.stringify(record.get('Session Information')));
});
fetchNextPage();
}, function done(err) {
if (err) { console.error(err); return; }
});
If I put it inside a Lambda handler - I get nothing.
const axios = require('axios')
const url = 'https://checkip.amazonaws.com/';
var Airtable = require('airtable');
var base = new Airtable({apiKey: 'keySECRETKEY'}).base('MYBASEID');
let response;
exports.lambdaHandler = async (event, context) => {
try {
base('MyBase').select({maxRecords: 3,view: "MyView"}).eachPage(function page(records, fetchNextPage) {
records.forEach(function(record) { //HERE - NOTHING HAPPENS
console.log('Retrieved',JSON.stringify(record.get('Session Information')));
});
fetchNextPage();
}, function done(err) {
if (err) { console.error(err); return; }
});
const ret = await axios(url); //THIS WORKS
response = {
'statusCode': 200,
'body': JSON.stringify({
message: 'hello world - boo',
location: ret.data.trim()
})
}
} catch (err) {
console.log(err);
return err;
}
return response
};
What am I missing so I can call Airtable API from inside an AWS Lambda?
It seems that your lambda terminates before the API call execution your trying to perform.
I believe this will be solved using a synchronous lambda or with a correct usage of promises with await calls.
Best way to troubleshoot this is to go back to the basics.
See if you can at least get a meaningful console log by wrapping a simpler fetch request into a lambda handler:
const baseId = 'exampleAppId123';
const tableName = 'Table 1';
const api_key = 'keyExample123';
const url = `https://api.airtable.com/v0/${baseId}/${tableName}?api_key=${api_key}`;
exports.lambdaHandler = async () => {
const res = await fetch(url)
.then(res => res.json())
.then(data=>console.log(data))
.then(() => {
//do more stuff
})
}
Then report back if you can't. Or better yet, report back either way as that's bound to help more people in the future.
Worst case? The above code still doesn't do anything. If that happens, I suggest going with #Shoty's first instinct and turning this code into a synchronous fetch request by removing the async/await syntax and returning chained thenables. Not that blocking behavior of this sort is acceptable from a UX perspective, but it should at least help with debugging.

How to handle HTTPs json format errors from APIs in Node.js?

INTRODUCTION
I am implementing a function for making any kind of https request to any endpoint (using the https native module). When I make a request to a specific API I get an error response in JSON format. Like this:
{
"error": {
"code": 404,
"message": "ID not found"
}
}
How can I handle this kind of errors? At a first moment, I supposed that they were handled in
request.on("error", (err) => {
reject(err);
});
HTTPs Request function code
I have comment '<---------' in the relevant parts of the code
const https = require("https");
exports.httpsRequest = function (options, body = null) {
/*
This function is useful for making requests over the HTTPs protocol
*/
return new Promise((resolve, reject) => {
const request = https.request(options, (response) => {
// Get the response content type
const contentType =
response.headers["content-type"] &&
response.headers["content-type"].split(";")[0];
// Cumulate data
let chuncks = [];
response.on("data", (chunck) => {
chuncks.push(chunck);
});
response.on("end", () => {
// Concat all received chunks
let response = Buffer.concat(chuncks);
// Some responses might be in JSON format...
if (contentType === "application/json") {
// Jsonify the response
response = JSON.parse(response);
}
// (For the future) TODO - Check and parse more content types if needed.
// Resolve the promise with the HTTPs response
resolve(response); // <--------- The JSON format error responses are resolved too!!
});
});
// Reject on request error
request.on("error", (err) => {
// <------------- At a first moment, I supposed that all error responses were handled in this part of the code
reject(err);
});
// Write the body
if (body) {
request.write(body);
}
// Close HTTPs connection.
request.end();
});
};
Question
Why the error response is not handled in request.on("error", ...) ?
Thank you. I would appreciate any help or suggestion.
You need to create a different code path for when the content type isn't what you were expecting in which you call reject() and you also need to try/catch around JSON parsing errors so you can properly catch them and reject on them too. You can solve those issues with this code:
exports.httpsRequest = function (options, body = null) {
/*
This function is useful for making requests over the HTTPs protocol
*/
return new Promise((resolve, reject) => {
const request = https.request(options, (response) => {
// Get the response content type
const contentType =
response.headers["content-type"] &&
response.headers["content-type"].split(";")[0];
// Cumulate data
let chuncks = [];
response.on("data", (chunck) => {
chuncks.push(chunck);
});
response.on("end", () => {
// Concat all received chunks
let response = Buffer.concat(chuncks);
// Some responses might be in JSON format...
if (contentType === "application/json") {
try {
// Jsonify the response
response = JSON.parse(response);
resolve(response);
return;
} catch(e) {
reject(e);
return;
}
}
reject(new Error("Not JSON content-type"))
});
});
// Reject on request error
request.on("error", (err) => {
reject(err);
});
// Write the body
if (body) {
request.write(body);
}
// Close HTTPs connection.
request.end();
});
};
FYI, libraries such as got() and others listed here, all do this work for you automatically and have a lot of other useful features. You don't really need to build this yourself.

using a fetch inside another fetch in javascript

I want to get an api and after that call another one. Is it wisely using a code like this in javascript?
fetch(url, {
method: 'get',
}).then(function(response) {
response.json().then(function(data) {
fetch(anotherUrl).then(function(response) {
return response.json();
}).catch(function() {
console.log("Booo");
});
});
})
.catch(function(error) {
console.log('Request failed', error)
});
Fetch returns a promise, and you can chain multiple promises, and use the result of the 1st request in the 2nd request, and so on.
This example uses the SpaceX API to get the info of the latest launch, find the rocket's id, and fetch the rocket's info.
const url = 'https://api.spacexdata.com/v4';
const result = fetch(`${url}/launches/latest`, { method: 'get' })
.then(response => response.json()) // pass the data as promise to next then block
.then(data => {
const rocketId = data.rocket;
console.log(rocketId, '\n');
return fetch(`${url}/rockets/${rocketId}`); // make a 2nd request and return a promise
})
.then(response => response.json())
.catch(err => {
console.error('Request failed', err)
})
// I'm using the result const to show that you can continue to extend the chain from the returned promise
result.then(r => {
console.log(r.first_stage); // 2nd request result first_stage property
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
There is not an issue with nesting fetch() calls. It depends on what you are trying to achieve by nesting the calls.
You can alternatively use .then() to chain the calls. See also How to structure nested Promises
fetch(url)
.then(function(response) {
return response.json()
})
.then(function(data) {
// do stuff with `data`, call second `fetch`
return fetch(data.anotherUrl)
})
.then(function(response) {
return response.json();
})
.then(function(data) {
// do stuff with `data`
})
.catch(function(error) {
console.log('Requestfailed', error)
});
This is a common question people get tripped up by when starting with Promises, myself included when I began. However, first...
It's great you're trying to use the new Fetch API, but if I were you I would use a XMLHttpRequest implementation for now, like jQuery AJAX or Backbone's overridden implementation of jQuery's .ajax(), if you're already using these libraries. The reason is because the Fetch API is still so new, and therefore experimental at this stage.
With that said, people definitely do use it, but I won't in my own production code until it's out of "experimental" status.
If you decide to continue using fetch, there is a polyfill available. NOTE: you have to jump through extra hoops to get error handling to work properly, and to receive cookies from the server. If you're already loading jQuery, or using Backbone, just stick with those for now; not completely dreadful, anyway.
Now onto code:
You want a flat structure, else you're missing the point of Promises. It's not wise to nest promises, necessarily, because Promises solve what nested async callbacks (callback hell) could not.
You will save yourself time and energy, and produce less buggy code by simply using a more readable code structure. It's not everything, but it's part of the game, so to speak.
Promises are about making asynchronous code retain most of the lost properties
of synchronous code such as flat indentation and one exception
channel.
-- Petka Antonov (Bluebird Promise Library)
// run async #1
asyncGetFn()
// first 'then' - execute more async code as an arg, or just accept results
// and do some other ops
.then(response => {
// ...operate on response data...or pass data onto next promise, if needed
})
// run async #2
.then(asyncGetAnotherFn)
.then(response => {
// ...operate on response data...or pass data onto next promise, if needed
})
// flat promise chain, followed by 'catch'
// this is sexy error handling for every 'then' above
.catch(err => {
console.error('Request failed', err)
// ...raise exeption...
// ... or, retry promise...
})
I didn't saw an answer with the syntactic sugar of async/await, so I'm posting my answer.
Another way to fetch "inside" another fetch in javascript is like -
try {
const response = await fetch(url, {method: 'get'});
const data = response.json();
//use the data...
const anotherResponse = await fetch(url, {method: 'get'});
const anotherdata = anotherResponse.json();
//use the anotherdata...
} catch (error) {
console.log('Request failed', error) ;
}
So actually you call url after url one by one.
This code will work inside async context.
I would use either an array of fetches instead or an array of urls, both in the order you would like to execute them. Then use reduce to execute them in sequence. This way it is much more scalable.
const urls = [
'https://api.spacexdata.com/v4/launches/latest',
'https://api.spacexdata.com/v4/launches/latest',
'https://api.spacexdata.com/v4/launches/latest'
];
// handle the fetch logic
// and handle errors
const handleFetch = async (url) => {
const resp = await fetch(url).catch(console.error);
return resp.json()
}
// reduce fetches, receives the response
// of the previous, log it (and maybe use it as input)
const reduceFetch = async (acc, curr) => {
const prev = await acc;
console.log('previous call:', prev);
return handleFetch(curr);
}
const pipeFetch = async urls => urls.reduce(reduceFetch, Promise.resolve(''));
pipeFetch(urls).then(console.log);
Is it wisely using a code like this in javascript?
Yes. Your code is fine.
Except that after the second request,
fetch(anotherUrl).then(function(response) {,
I would replace return response.json();
with response.json().then(function(data2) { – just as after the
first request.
The variable data2 will then contain the response body of the inner
URL request, as desired.
This means that – whatever you want to do with data2, you must do it
inside this second callback (since you don't return a promise.)
Also, a few more printouts will help to understand what is happening.
1. The original code – slightly modified
After making those changes, here is a Stack Snippet containing your
code:
1
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const anotherUrl = 'https://jsonplaceholder.typicode.com/todos/4';
fetch(url, {
method: 'get'
}).then(function (response) {
response.json().then(function (data) {
console.log('Response body of outer "url":');
console.log(JSON.stringify(data) + '\n\n');
fetch(anotherUrl).then(function (response) {
response.json().then(function (data2) {
console.log('Response body of inner "anotherUrl":');
console.log(JSON.stringify(data2) + '\n\n');
});
}).catch(function () {
console.log('Booo');
});
});
})
.catch(function (error) {
console.log('Request failed', error);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
which is fine really, although the fat arrow style is more common
these days for defining a function.
2. The code refactored
Here is a refactored version of your code.
It has an inner chained/nested request – fetch(urlInner) – that
depends on data retrieved from a previous/outer request: fetch (urlOuter).
By returning the promises of both the outer and the inner URL fetches,
it is possible to access/resolve the promised result later in the code:
2
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://jsonplaceholder.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
Note that no indentation is deeper than eight spaces.
3. Advantages of this code style
This is clearly a nested style of writing the code – meaning that the
chained request fetch(urlInner) is indented and made inside the
callback of the first request fetch(urlOuter).
Yet, the indentation tree is reasonable, and this style resonates well
with my intuition about chaining requests. – But more importantly,
this style makes it possible to write error messages that pinpoint
which URL failed.
Run the snippet below to see how the error message tells that it is the
inner/second URL that causes the error:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
4. Flattening all occurrences of .then()?
Inspired by others, you may be tempted to flatten all occurrences of
.then(), like below.
I would advise against doing this – or at least think twice before
doing it. Why?
In the absence of errors, it doesn't matter.
If there are errors, such a style will force less distinct error
messages:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner);
})
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch one or more of these URLs:');
console.log(urlOuter);
console.log(urlInner);
console.log(err);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
The code is nicely flat, but the error caught at the end cannot decide
which of the URL requests that failed.
1 All snippets of this answer comply with the
JavaScript Semistandard Style.
2 About line 11 – return fetch(urlInner) – it is
very easy to forget to return the fetch.
(I once forgot it even after writing this answer.)
If you do forget it, resultPromise will not contain any promise at
all.
The last three lines in the snippet will then fail – they will output
nothing.
The result fails completely!
just some ways of doing it.
1, using async -await
app.get("/getemployeedetails/:id", async (req, res) => {
const id = req.params.id;
const employeeUrl = "http://localhost:3000/employee/" + id;
try {
const response = await fetch(employeeUrl);
const employee = await response.json();
const projectUrl = "http://localhost:3000/project/" + employee.project_id;
const response1 = await fetch(projectUrl);
const project = await response1.json();
const result = {
...employee,
...project,
};
res.send(result);
} catch (error) {
console.log("getData: ", error);
}
});
2, chaining of then
app.get("/getemployeedetails/:id", (req, res) => {
const id = req.params.id;
const employeeUrl = "http://localhost:3000/employee/" + id;
let employeeResponse = null;
fetch(employeeUrl)
.then((employee) => employee.json())
.then((resp) => {
employeeResponse = resp
const projectUrl =
"http://localhost:3000/project/" + employeeResponse.project_id;
return fetch(projectUrl);
})
.then((project) => project.json())
.then((projectResponse) => {
const result = {
...employeeResponse,
...projectResponse,
};
res.send(result);
})
.catch((err) => console.log(err));
});
3, chaining in a better way
app.get("/getemployeedetails/:id", (req, res) => {
const id = req.params.id;
getEmployeeResponse(id).then((employeeResponse) => {
getProjectResponse(employeeResponse.project_id)
.then((projectResponse) => {
const result = {
...employeeResponse,
...projectResponse,
};
res.send(result);
})
.catch((err) => console.log(err));
});
});
function getEmployeeResponse(id) {
return new Promise((resolve, reject) => {
const employeeUrl = "http://localhost:3000/employee/" + id;
fetch(employeeUrl)
.then((employee) => employee.json())
.then((resp) => resolve(resp))
.catch((err) => reject(err));
});
}
function getProjectResponse(id) {
return new Promise((resolve, reject) => {
const projectUrl = "http://localhost:3000/project/" + id;
fetch(projectUrl)
.then((project) => project.json())
.then((resp) => resolve(resp))
.catch((err) => reject(err));
});
}
you decide.
I suggest using axios, is much better and you don't have to deal with JSON format. Also, the code looks cleaner and is easier to understand.
axios.get(firstUrl).then((resp1) => {
// Handle success of first api
axios.get(secondUrl).then((resp2) => {
return resp2.data
}).catch((error) => { /* Handle error of second api */ });
}).catch((error) => { /* Handle error of first api */ });
Blockquote from LogRocket.com:
As with Fetch, Axios is promise-based. However, it provides a more
powerful and flexible feature set.
Advantages of using Axios over the native Fetch API include:
Request and response interception
Streamlined error handling
Protection against XSRF
Support for upload progress
Response timeout
The ability to cancel requests
Support for older browsers
Automatic JSON data transformation

Categories