How to use fetch to send a variable to a GET request? - javascript

I am having an issue with using fetch to send an id which is then sent to a get request in the backend which performs a function.
The aim of the function is to delete the element from the JSON file which is entered into the input box in the front end.
However, when I do this, I get an error saying the route for the function is not found:
GET http://localhost:3000/delete 404 (Not Found)
This is the code for the /delete route:
app.get('/delete/:id', function (req, res) {
var id = req.params.id;
for (var i = 0; i < tasksArray.length; i++) {
if(tasksArray[i].id == id) {
tasksArray.splice(i, 1);
}
}
res.json(tasksArray);
var json = JSON.stringify(tasksArray);
fs.writeFileSync("toDoList.json", json);
});
This is the code for the front end with fetch:
function deleteElement() {
var id = document.getElementById("deleteId").value;
var url = "http://localhost:3000/delete";
fetch(url, {
method: 'GET',
url: `/delete/${id}`,
headers: {
'Content-Type': 'application/json'
}
});
}
Any help is appreciated.

You were not using id in the url.
function deleteElement() {
var id = document.getElementById("deleteId").value;
var url = "http://localhost:3000/delete/" + id;
fetch(url, {
// removed url as it's defined in fetch's first arguments.
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
}

Related

API returning one result instead of multiple 11ty/eleventy-fetch Promise.all call

I've got an 11ty project (static site generator) where I'm fetching property data then using this data in a Promise.all call to:
fetch all property images and
fetch tenancy application urls
Then add these into one array labeled allData for my pages.
Image call is working fine but the tenancy api call is not.
I'm changing the api body I'm sending to to the tenancy api by using the i from Promise.all and this seems to be working from my console.logs but the result I'm getting is the same tenancy link being returned for each call.
I feel like it might have something to do with the order I'm calling fetch/using Promise.all because if I add a hello console log my an array with i label will log followed by hello, then the next e.g. body 1 hello, body 2 hello, etc. and then all the tpResponses (urls) will log in a row.. which doesn't seem right. I can't see the actual requests going through since this is done in build time so I'm a little confused but I'm guessing only one apibody is being sent based on results.
I've tried using .then for the fetch calls but think I configured this wrong. Do I need to use .then for the fetch calls or something other than Promise.all and how would that work?
Code below. Any help would be appreciated!
require('dotenv').config();
const EleventyFetch = require("#11ty/eleventy-fetch");
const crypto = require('crypto');
async function getPropertyData(){
console.log("getPropertyData...")
//Property vars
var username = process.env.MANOR_USERNAME;
var password = process.env.MANOR_PASSWORD;
var auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
//Tenancy vars
var api_public_key = process.env.TPS_KEY;
var api_secret = process.env.TPS_SECRET
let api_url = "https://www.tpsportal.co.nz/api/v1/tenancy_application/create_property"
function sign(endpoint, key, secret, date, body) {
const encoded = new
Buffer([endpoint,body,date].join('\n')).toString('base64');
return crypto
.createHash('sha256')
.update(encoded + '+' + secret, 'utf8')
.digest()
.toString('hex');
}
//Get Property Details
const url = `https://api.getpalace.com/Service.svc/RestService/v2AvailableProperties/JSON`
const response = EleventyFetch(url, {
duration: "1d",
type: "json",
fetchOptions: {
headers: {
accept: 'application/json',
'content-type': 'application/json',
'Authorization': auth
}
}
})
const properties = await response;
//Create URLs for Image call
let propertyImageUrls = []
properties.forEach(property => {
propertyImageUrls.push(`https://api.getpalace.com/Service.svc/RestService/v2AvailablePropertyImagesURL/JSON/${property.PropertyCode}`)
});
let allData = [];
//Fetch Property Images
const allPropertyImages = await Promise.all(propertyImageUrls.map(async (url,i) => {
const imageResponse = await EleventyFetch(url, {
duration: "1d",
type: "json",
fetchOptions: {
headers: {
accept: 'application/json',
'content-type': 'application/json',
'Authorization': auth
}
}
});
let tpData;
const imageData = await imageResponse;
//Add property matching details + image to allData array
let apibody = JSON.stringify({
client_code: "8754",
property_code: properties[i].PropertyCode,
agent_name: properties[i].PropertyAgent.PropertyAgentFullName,
agent_email: properties[i].PropertyAgent.PropertyAgentEmail1,
unit: properties[i].PropertyUnit,
street_number: properties[i].PropertyAddress1,
street_name: properties[i].PropertyAddress2,
suburb: properties[i].PropertyAddress3,
city: properties[i].PropertyAddress4,
postcode: properties[i].PropertyFeatures.PropertyPostCode
})
console.log("API BODY " + i +" :",apibody)
var api_date = new Date().toISOString();
var signature = sign(api_url,api_public_key,api_secret,api_date,apibody)
console.log('hello')
let tpResponse = await EleventyFetch(api_url, {
duration: "1d",
type: "json",
fetchOptions: {
method: 'post',
headers: {
accept: 'application/json',
'content-type': 'application/json',
'X-API-DATE': api_date,
'X-API-KEY': api_public_key,
'X-API-SIGNATURE': signature
},
body: apibody
}
})
console.log("tpResponse: ", apibody)
tpData = await tpResponse;
console.log("tpData: ", tpData)
This is the error: tpData is just giving me the same link for each property instead of different links
allData.push([properties[i], imageData, tpData])
}))
// console.log(allData)
return allData;
}
module.exports = getPropertyData;

Node.js - using request to send multiple HTTP GET's in a for loop

I'm trying to send multiple HTTP requests from my node.js server (using the 'request' package) in a for loop.
The idea is to basically have an array of URLs, send a HTTP get for each one, and store the response in an array called 'responseArray'.
When I try this, I get 'undefined', but I know the requests are working if I log them to the console inside the for loop.
function apiCalls() {
var URLs = [‘URL1’, ‘URL2’, ‘URL3’];
var responseArray = []
for (var i = 0; i < URLs.length; i++) {
request({
url: URLs[i],
method: 'GET',
headers: {
'Connection': 'close'
},
}, function(error, response, body) {
if (error) {
console.log(error);
} else {
responseArray.push(String(response.body));
console.log(responseArray) // this is showing me all the data in the array correctly
return responseArray;
}
}) //end request function
} //end for loop
console.log(responseArray)
} //end apiCalls function
apiCalls()
So after looking at a few different solutions here on stack overflow and elsehwere I tried using promises. I've never used them before and based this off the google example
Promise:
var apiCalls = new Promise(function(resolve, reject) {
var URLs = [‘URL1’, ‘URL2’, ‘URL3’];
var responseArray = [];
for (var i = 0; i < URLs.length; i++) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
request({
url: URLs[i],
method: 'GET',
headers: {
'Connection': 'close'
},
}, function(error, response, body) {
if (error) {
console.log(error);
} else {
resolve(responseArray.push(String(response.body))
}
}) //end request
} //end for loop
})
apiCalls.then(function(result) {
console.log('this is calling the promise')
console.log(result)
}, function(err) {
console.log(err)
});
I always get an empty array when I try to log the responseArray after the for loop. Alternatively - I get 'undefined' if I try to assign the returned array to a variable like so:
var gimmeAllResponses = apiCalls();
console.log(gimmeAllResponses); //returns 'undefined'
Can anyone show me where I'm going wrong? how do I updated the 'responseArray' data after the for loop has finished?
This is a little bit off, since this requires the alternative package, request-promise.
You're resolving many times. Since you're using Node.js, it's very likely that ES6 features are available. Use Array.prototype.map() and Promise.all():
var rp = require('request-promise');
var URLs = [‘URL1’, ‘URL2’, ‘URL3’];
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var responseArray = Promise.all(URLs.map((url) => rp({
uri: url,
method: 'GET',
headers: {
'Connection': 'close'
}
}).then((error, response, body) => {
if (error) {
console.log(error);
} else {
return String(response.body);
}
})));

Unable to paginate on a callback function

I'm trying to paginate on a call to callback function but getting an error over second call
my function does:
let content = ''
let size = 100
let from = 1
function result(size, from, callback) {
api.performRequest('/myContents', 'GET', {
pageSize: size,
startFrom: from,
filter:'NOT contents:[* TO *]',
}, function (data) {
content += JSON.stringify(data)
callback()
})
}
function logContent() {
const parsed = JSON.parse(content)
console.log('content length: ', parsed.body.length)
if (parsed.body.length === size) {
calculate(size, from + size)
}
}
function calculate(size, from) {
result(size, from, logContent)
}
calculate(size, from)
on the first call the console returns
content length: 100
on the second call I get all my json chunk on the logs and an error
Unexpected token { in JSON at position 32847
I think it has to do with the callback and something happening before the function finishes, but I'm unable to see what I'm doing wrong here
the function performRequest just does an http get and returns a json chunk
export function performRequest(endpoint, method, data, callback) {
const headers = {
Authorization: auth,
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Expose-Headers': 'Location,ETag',
}
let options = {
host: host,
port: port,
path: endpoint,
headers: headers,
}
if (method === 'GET') {
endpoint += '?' + queryString.stringify(data)
const additionalOptions = {
path: endpoint,
}
options = _.merge(options, additionalOptions)
}
return http.get(options, function (response) {
// Continuously update stream with data
let body = ''
response.on('data', function (d) {
body += d
})
response.on('end', function () {
// Data reception is done
const parsed = JSON.parse(body)
callback({
totalCount: parsed.totalCount,
body: parsed.content,
})
})
})
}
Your first call is going to be fine, because your content is empty at first. So, during the first call:
content = '' --> content = '{...}'
And your second call :
content = '{...}' --> content = '{...}{...}'
Thus the error :
Unexpected token { in JSON at position 32847
You need to put every objects in an array, or even in another object if you want it to work. You can create an array and push every element into it at every call.

Execute second function after first function - REST

If the first REST function execute with sucess, the second it will be execute with the parameters of the first function, in the case return: sessionid and I save the value inside variable sessionid
Both functions are REST call within the same .js file.
In the case I trying:
My restApiCall.js file:
var Client = require('./lib/node-rest-client').Client;
var client = new Client();
var dataLogin = {
data: { "userName":"xxxxx","password":"xxxxxxxxxx","platform":"xxxx" },
headers: { "Content-Type": "application/json" }
};
var numberOrigin = 350;
client.registerMethod("postMethod", "xxxxxxxxxxxxxxxxxx/services/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
// parsed response body as js object
// console.log(data);
// raw response
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
re = /(sessionID: )([^,}]*)/g;
match = re.exec(data);
var sessionid = match[2]
console.log(sessionid);
openRequest(sessionid, numberOrigin); // I try execute, but just the first execute if I type inside Prompt command: node restApiCall
}
});
// this is the second function I want execute after the first sucess
function openRequest(sessionid, numberOrigin){
var client = new Client();
numberOrigin+=1;
var dataRequest = {
data: {"sessionID":sessionid,"synchronize":false,"sourceRequest":{"numberOrigin":numberOrigin,"type":"R","description":"Test - DHC","userID":"xxxxxxxxxx","contact":{"name":"Sayuri Mizuguchi","phoneNumber":"xxxxxxxxxx","email":"xxxxxxxxxxxxxxxxxx","department":"IT Bimodal"},"contractID":"1","service":{"code":"504","name":"Deve","category":{"name":"Developers"}}} },
headers: { "Content-Type": "application/json" }
};
client.post("xxxxxxxxxxxxxxxxxxxxxxxxx/services/request/create", dataRequest, function (data, response) {
// parsed response body as js object
// console.log(data);
// raw response
console.log(response);
});
}
Thanks advance.
In the case the problem is new Client(); because the client have definied with line 2 and dont necessary declare again.
I use this code and works fine.
var Client = require('./lib/node-rest-client').Client;
var client = new Client(); //defined
var dataLogin = {
data: { "userName":"xxxxx","password":"xxxxxxxxxx","platform":"xxxx" },
headers: { "Content-Type": "application/json" }
};
var numberOrigin = 350;
client.registerMethod("postMethod", "xxxxxxxxxxxxxxxxxx/services/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
// parsed response body as js object
// console.log(data);
// raw response
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
re = /(sessionID: )([^,}]*)/g;
match = re.exec(data);
var sessionid = match[2]
console.log(sessionid);
openRequest(sessionid, numberOrigin); // execute fine
}
});
function openRequest(sessionid, numberOrigin){
numberOrigin+=1;
var dataRequest = {
data: {"sessionID":sessionid,"synchronize":false,"sourceRequest":{"numberOrigin":numberOrigin,"type":"R","description":"Test - DHC","userID":"xxxxxxxxxx","contact":{"name":"Sayuri Mizuguchi","phoneNumber":"xxxxxxxxxx","email":"xxxxxxxxxxxxxxxxxx","department":"IT Bimodal"},"contractID":"1","service":{"code":"504","name":"Deve","category":{"name":"Developers"}}} },
headers: { "Content-Type": "application/json" }
};
client.post("xxxxxxxxxxxxxxxxxxxxxxxxx/services/request/create", dataRequest, function (data, response) {
// parsed response body as js object
// console.log(data);
// raw response
console.log(data);
});
}

Working with OfflineJS and AngularJS

I am working on an angular app where I want to integrate OfflineJS functionality.
I have created a general service for getting and posting data to/from an API,and a specific service for each module.
Here is the code
app.service('MethodProvider', function ($http) {
var self = this;
self.get = function (url) {
var obj = {
url: url,
method: 'GET',
async: true,
headers: {
'Content-Type': 'application/json'
}
};
return $http(obj);
};
self.post = function (url, data) {
var obj = {
url: url,
method: 'POST',
async: true,
data: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
};
return $http(obj);
};
self.put = function (url, data) {
var obj = {
url: url,
method: 'PUT',
async: true,
headers: {
'Content-Type': 'application/json'
}
};
if (typeof data != 'undefined' && data != null) {
obj.data = JSON.stringify(data);
}
return $http(obj);
};
self.delete = function (url) {
var obj = {
url: url,
method: 'POST',
async: true,
headers: {
'Content-Type': 'application/json'
}
};
return $http(obj);
};
return self;
});
And a specific module service like User module
app.service('UserSrvc', function (MethodProvider) {
var self = this;
self.create = function (data) {
var url = apiUrl + '/user/add';
return MethodProvider.post(url, data);
};
return self;
});
How do I integrate OfflineJS in this code , I want to intercept HTTP request when network connectivity is down and resume requests when network connectivity is up . I have studied this example but unable to integrate this in angular need an example to get started.
hope this helps the future users:
Offlinejs adds Offline object to the global window object.
Offlinejs does not trigger check() by itself (it does it once if checkOnLoad option is set to true).
You may call Offline.check() just before you make an ajax request to your server and check for connection.
You can also do polling, if your app is xhr intensive.
var run = function(){
if(Offline.state=="up")
Offline.check();
};
setInterval(run, 20000); // check after 20sec
Offline.on('down',function(){ /**code to handle network down*/ });
As pointed by #Adnan Umer You need to set Offline.options = { interceptRequests: true, requests: true }
to intercept failed requests and try again once connection is back.
One caveat here is that the requests resent by Offline will be out of the scope of Angular, accordingly, all the GET requests will result to nothing. Which is actually fine, usually the user initiates the get requests.
Offline.options = {
checks: {xhr: {url: "put_url_to_check_status_of_your_server"}}
}
By default, Offlinejs checks for favicon.ico.

Categories

Resources