I am trying to use an API from https://api-ninjas.com/api/geocoding/. Their site provides the following starter code for how to call an API, but when I try it, the browser console just tells me that $ is not defined.
Is $.ajax a stand-in for something I need to create?
Here is the starter code they provide:
var city = 'london'
$.ajax({
method: 'GET',
url: 'https://api.api-ninjas.com/v1/geocoding?city=' + city,
headers: { 'X-Api-Key': 'YOUR_API_KEY'},
contentType: 'application/json',
success: function(result) {
console.log(result);
},
error: function ajaxError(jqXHR) {
console.error('Error: ', jqXHR.responseText);
}
});
I have tried writing document.ajax, but that returned the error that it was not a function. I have also tried deleting $.ajax and putting fetch in its place
I was able to solve with the following code:
let options = {
method: 'GET',
headers: { 'x-api-key': 'myKey' }
}
let url = 'https://api.api-ninjas.com/v1/geocoding?city=denver'
fetch(url,options)
.then(res => res.json()) // parse response as JSON
.then(data => {
console.log(data)
})
.catch(err => {
console.log(`error ${err}`)
});
I'm trying to force Node to wait for either a success or a failure. I understood fetch to return a promise and I thought I told it how to handle both.
The following code does not honor the await I asked it to do:
async function getAccessToken() {
...
let fetchResult = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers: headers
}).then(success => {
console.log("Success reached. " + JSON.stringify(success));
process.exit(2);
}, other => {
console.log("Other reached. " + JSON.stringify(other));
process.exit(3);
});
console.log('## after fetch fetchResult=' + fetchResult);
...
}
You might think that the await would cause it to, wait for the Promise to complete, but instead it leaves the whole function, and goes back to the caller. It does not print the '## after fetch fetchResult=' line. Neither the failure, nor success handler is executed.
I should point out that it also does not appear to make the requested POST call either. Instead, it sees that request and does something completely different without raising any exception.
Why is it not honoring the 'await' keyword whatsoever?
--- If I try the try/catch approach as follows:
async function getAccessToken() {
console.log('##getAccessToken BP1');
if (argumentParserResult.authenticationScheme == 'OAUTH2') {
console.log('##getAccessToken BP2');
const fetch = require('node-fetch');
const url = argumentParserResult.resourceUrl;
console.log('##getAccessToken BP3');
let formData = new URLSearchParams({
'grant_type': 'client_credentials',
'client_id': argumentParserResult.clientId,
'scope': argumentParserResult.clientScope,
'client_secret': argumentParserResult.clientSecret
})
console.log('##getAccessToken BP4');
let headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
console.log('##getAccessToken BP5');
console.log('POST ' + argumentParserResult.authorizationUrl);
console.log(JSON.stringify(formData));
console.log('##getAccessToken BP6');
try {
console.log('##getAccessToken BP7');
const response = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers,
});
console.log('##getAccessToken BP8');
console.log(`Success reached.`, JSON.stringify(response));
const json = await response.json();
console.log('##getAccessToken BP9');
console.log(`Other reached.`, json);
return json;
} catch (error) {
console.log('##getAccessToken BP10');
console.log(`!! something went wrong`, error.message);
console.error(error);
return error;
} finally {
console.log('##getAccessToken BP11');
console.log(`fetch finished`);
}
console.log('##getAccessToken BP12');
}
console.log('##getAccessToken BP13');
return "Should not have reached this point";
}
I get
##getAccessToken BP1
##getAccessToken BP2
##getAccessToken BP3
##getAccessToken BP4
##getAccessToken BP5
POST https://some-url
{}
##getAccessToken BP6
##getAccessToken BP7
As you can see, it goes just inside of the try block, then goes back to the caller without triggering the finally, error handlers or the logging after the fetch.
Using the .then approach as follows:
async function getAccessToken() {
console.log('##getAccessToken BP1');
if (argumentParserResult.authenticationScheme == 'OAUTH2') {
console.log('##getAccessToken BP2');
const fetch = require('node-fetch');
const url = argumentParserResult.resourceUrl;
console.log('##BP1.9');
let formData = new URLSearchParams({
'grant_type': 'client_credentials',
'client_id': argumentParserResult.clientId,
'scope': argumentParserResult.clientScope,
'client_secret': argumentParserResult.clientSecret
})
console.log('##getAccessToken BP3');
let headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
console.log('##getAccessToken BP4');
console.log('POST ' + argumentParserResult.authorizationUrl);
console.log(JSON.stringify(formData));
let response = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers: headers
}).then(success => {
console.log('##getAccessToken BP5');
console.log("Success reached. " + JSON.stringify(success));
return success // !--> LOOK HERE, you should return the success variable
}).catch(e => {
console.log('##getAccessToken BP6');
console.log(e) // !--> LOOK HERE, if you catch the error, no error will be thrown to the caller
return e
});
console.log('##getAccessToken BP7');
console.log('## after fetch fetchResult=', fetchResult); // !--> LOOK HERE, this log will always log something now, it could be the responso or the error
}
console.log('##getAccessToken BP8');
}
I get these logs:
##getAccessToken BP1
##getAccessToken BP2
##BP1.9
##getAccessToken BP3
##getAccessToken BP4
POST https://login.microsoftonline.com/5a9bb941-ba53-48d3-b086-2927fea7bf01/oauth2/v2.0/token
{}
As you can see above, it goes just to the point of the fetch, then returns to the calling function.
In neither case, can I see any evidence that the fetch was ever called.
Try this:
async function getAccessToken() {
try {
const response = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers,
});
console.log(`Success reached.`, JSON.stringify(response));
const json = await response.json();
console.log(`Other reached.`, json);
} catch (error) {
console.log(`!! something went wrong`, error.message);
console.error(error);
} finally {
console.log(`fetch finished`);
}
}
You don't need to use thenable object when writing with async/await, instead, catch the error with a try catch bloc, and just get the async value using return of awaited function.
You are mixing await and then. It is not forbidden, but in most simple case you don't need it.
Solution without then:
async function getAccessToken() {
try {
console.log('fetching data') // this log will always appear as first log, before fetching data
let fetchResult = await fetch(argumentParserResult.authorizationUrl,
{
method: 'POST',
body: formData,
headers: headers
})
let jsonR = await fetchResult.json()
console.log('fetch done') // this log will appear only if fetch is done with no errors
} catch (e) {
console.error('something went wrong', e) // this log will appear only if there was an error
}
console.log('after all') // this log will appear always, after fetch (even if fetch fails or not)
}
Solution with then:
async function getAccessToken() {
let fetchResult = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers: headers
}).then(success => {
console.log("Success reached. " + JSON.stringify(success));
return success // !--> LOOK HERE, you should return the success variable
}).catch(e => {
console.log(e) // !--> LOOK HERE, if you catch the error, no error will be thrown to the caller
return e
});
console.log('## after fetch fetchResult=', fetchResult); // !--> LOOK HERE, this log will always log something now, it could be the responso or the error
}
As you can see, error handling is not quite convenient in the second solution. That's why you should not mix await with then, unless you know what you are doing
The point of async/await is to get rid of the callbacks and make the code more procedural. Your code:
async function getAccessToken() {
...
let fetchResult = await fetch(argumentParserResult.authorizationUrl, {
method: 'POST',
body: formData,
headers: headers
})
.then( success => {
console.log("Success reached. " + JSON.stringify(success));
process.exit(2);
}, other => {
console.log("Other reached. " + JSON.stringify(other));
process.exit(3);
});
console.log('## after fetch fetchResult=' + fetchResult);
...
}
fails, because you are
Waiting for fetch() to resolve and return a result, and
In your then() chain, you are
Invoking process.exit() in the case of either success or failure.
Than means you kill the entire process as soon as the call to fetch() resolves with either a success or a failure.
If you do something like this:
async function getAccessToken() {
...
const opts = {
method: 'POST',
body: formData,
headers: headers
};
const {json, err} = await execFetch( argumentParserResult.authorizationUrl, opts );
if ( err ) {
console.log("that didn't work!", err);
process.exit(1);
}
...
}
async function execFetch( url, opts ) {
const response = { json: undefined, err: undefined };
const { res, err } = await fetch( argumentParserResult.authorizationUrl, opts )
.then( res => ({ res , err: undefined }) )
.catch( err => ({ res: undefined , err }) );
if ( err ) {
response.err = err;
}
else if ( !res.ok ) {
// non-2xx HTTP status
response.err = new Error(`${res.status}: ${res.statusText}`);
}
else {
// the 2xx happy path: deserialize the JSON response body into a JS object
response.json = res.json();
}
return response;
}
Your call to fetch() will always succeed and hand you back a tuple with a json and an err property.
A successful call will return something like this:
{
json: { a: 1, b: 2, c: 3, },
err: undefined,
}
Whilst a call to fetch() that fails will return something like this:
{
json: undefined ,
err: /* some error object with details about what went south */,
}
I'm using a url shortner API to test connecting to a API and I keep getting a 400 BadRequest. I've read through a dozen posts here and tried all suggestions and still nothing will work. I don't know what I'm doing wrong.
Function
var axios = require('axios');
module.exports = function (callback, data) {
let url = 'https://cleanuri.com/api/v1/shorten';
let axiosConfig = {
"headers": {
'Content-Type': 'application/json;charset=UTF-8'
}
};
let longUrl = { "url" : data };
axios(url, {
method: "post",
params: {
"url" : data
},
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
})
.then(function (response) {
callback(null, response.data);
}).catch(function (err) {
console.log("error: " + err.response);
callback(err, null);
});
I've also tried this and got same error
axios.post(url, JSON.stringify(longUrl), axiosConfig)
.then(function (response) {
callback(null, response.data);
}).catch(function (err) {
console.log("error: " + err.response);
callback(err, null);
});
To send data as body use data field on request options
const payload = { ... }
axios({ ..., data: payload })
params field is used to send query string within url
I have read your api docs https://cleanuri.com/docs.
That requiring your payload send as body, so use data field
Here the snippet:
let payload = { "url" : data };
axios(url, {
method: "post",
data: payload,
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
})
Edit:
400 Bad Request is indicating your request is invalid (by server)
I am trying to sent my form data to node js and retrieve at there.But I am failed to do it with form data object.
handleSubmit(data) {
console.log(data);
const forms=new FormData();
forms.append('fname','pranab');
let promise=fetch('http://localhost:8080/reactTest', {
method:'POST',
mode:'CORS',
body:JSON.stringify(forms),
headers:{
'Content-Type':'application/json',
'Accept':'application/json'
}
}).then(res =>res.json()).then(result => console.log(result))
}
in the above code I am sending form data object to the serve side.At the server side I am trying to retrieve it using below code.
app.post('/reactTest',function(req,res) {
var contents=req.body;
console.log(contents);
return res.send({status:'working'});
})
but it displays nothing in the console.What the issue here is?
output is
titech#titech-System-Product-Name:/var/www/html/nodejs$ node index.js
port listening on 8080
{}
when i trying to console it with 'req.body.fname' it gives 'undefined' as output in place of '{}'.
Looks like you need some function to convert formData to JSON. Like this one:
function formData2Json(formData){
let ret={};
for(let pair of formData.entries()) {
let val=ret[pair[0]];
if (!val) {
ret[pair[0]]=pair[1];
}
else {
if (Array.isArray(val)) {
val.push(pair[1]);
}
else {
ret[pair[0]]=[val,pair[1]];
}
}
}
return ret;
}
and than replace body:JSON.stringify(forms) with body:JSON.stringify(formData2Json(forms))
try this it may help
var bodyFormData = new FormData();
bodyFormData.set('userName', 'Fred');
axios({
method: 'post',
url: 'myurl',
data: bodyFormData,
config: { headers: {'Content-Type': 'multipart/form-data' }}
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
I am building an application and having an issue with making a request from the client, sending it to my server, having the server make the API call and then send the result back to the client. I am using Node and the Request-Promise module.
Here is the client side code:
$(document).ready(function() {
var artistSearch = () => {
const q = $('.artistName').val();
$.ajax({
type: "POST",
url: "http://localhost:3000/request",
data: {artist: q},
})
.done(function(data) {
console.log('data: ', data)
})
};
$(".artistSearch").submit( () => {
artistSearch();
});
});
This successfully makes a request to the server:
app.post('/request', (req, res) => {
const artist = req.body.artist;
const searchURL = "https://api.spotify.com/v1/search? q="+artist+"&type=artist";
var targetObj;
var options = {
uri: searchURL
};
rp(options)
.then(function (data) {
console.log(data);
res.send(data);
})
.then(function() {
console.log('complete');
})
.catch(function (err) {
console.log('error')
});
});
Which ultimately successfully grabs the data from the API call, but never sends it back to the client! If I do res.send() outside of my .then promise, I can receive data on the client end.
Is there something I am missing? Thanks in advance!
Try this
var options = {
uri: searchURL,
simple: false,
};
rp(options)
.then(function (data) {
console.log(data);
res.status(200).send(data).end();
})
.then(function() {
console.log('complete');
})
.catch(function (err) {
console.log('error')
});
I think the client did receive data, but the connection didn't terminate correctly as it thinks there are more data. This is because you didn't specify the header and the module http couldn't figure out the content-length.
rp(options)
.then(function (data) {
console.log(data);
// res.send(data);
// assume data is JSON.
res.setHeader (200, {'Content-Type': 'application/json',
'Content-Length':data.byteLength});
res.end(data); //Send data immediately.
})
...
If data is a string, you will need to use data.length instead. In fact, if data is a string, then by default the header is {'Content-Type': 'application/json', 'Content-Length':data.length}