Call function with request options from another function always empty - javascript

I have a code like below. I am running a calling a function searchApiData. In searchApiData, when I log data in console I can see values of body. But when I see from exports.readData console.log(returnData), the value is always empty. Anyone know how I can get the data of the body in searchApiData?
exports.readData = functions.https.onRequest(async (req, res) => {
var returnData = "";
for (var a = 0; a < emailList.length; a++) {
returnData = searchApiData(emailList[a]);
console.log(returnData);
}
})
function searchApiData(email) {
fsData = "";
const options = {
method: 'GET',
json: true,
url: FS_URL + 'api/lookup?f=email&q='+email+'&entities=contact',
headers: {
"Authorization": "Token token=" + FS_API_KEY,
"Content-Type": "application/json"
}
};
//call the request
request(options, function(error, response, body) {
if(!error && response.statusCode == 200){
console.log(body);
fsData = body;
} else{
console.log(error);
}
});
return fsData;
}

Related

Catch Google Cloud function errors in POST

I have this cloud function that append a line to a Google Spreadsheet:
function addLine(req, res) {
res.set("Access-Control-Allow-Origin", "*");
if (req.method === "OPTIONS") {
res.set("Access-Control-Allow-Methods", "POST");
res.set("Access-Control-Allow-Headers", "Content-Type");
res.set("Access-Control-Max-Age", "3600");
return res.status(204).send("");
}
const isReqValid = validateReq(req);
if (!isReqValid) return res.send("Not valid request!"); // <--
const { body } = req;
const isBodyValid = validateData(body);
if (!isBodyValid) return res.send("Not valid payload!"); // <--
return appendData(body)
.then(() => res.send("Added line"))
.catch((err) => {
res.send("Generic error!");
});
}
function validateReq(req) {
if (req.method !== "POST") return false;
return true;
}
function validateData(data) {
// do something and return true or false
}
async function appendData(data) {
const client = await auth.getClient();
return sheets.spreadsheets.values.append(
{
spreadsheetId: ...,
auth: client,
range: "A1:B",
valueInputOption: "RAW",
resource: { values: [data] },
},
);
}
I use it in this way:
async collaborate(data: CollaborateDatum) {
await post('...cloudfunctions.net/addLine', data)
}
async function post(url, data) {
return fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
}
How can I "read" the errors Not valid request! and Not valid payload!? Because if I tried to append a line with not valid data, I get status code 200 but in Chrome Dev Tools -> Network -> Response, the response is Not valid payload! but I don't know how to catch this error.
Thanks a lot!
You should be able to get any response text that's passed back like this:
let responseText = await (await post('...cloudfunctions.net/addLine', data)).text();

How to wait until request.get finish then conduct the next block in node.js

I am new to NodeJS and I am working on a request.get problem. My goal is simply have a function that request the web, and when request finished, the function returns the result, otherwise it returns an error message.
Here's the function that I used for request:
var artistNameIdMap = {};
var getPopularArtists = async () => {
//https://nodejs.org/api/http.html#http_http_request_options_callback
var options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
json: true
}
request.get(options, function(error, response, body) {
if (response.statusCode === 200){
console.log("inside");
artistNameIdMap = getArtistNameIdMap(body, artistNameIdMap);
} else {
res.send("get popular error");
return {};
}
})
console.log("outside");
return artistNameIdMap;
module.exports = {
GetPopularArtists: getPopularArtists
}
And this function is included in a getPopular.js file. I would like to call the function in another file playlist.js.
In playlist.js, I wrote
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", (req, res) =>{
const artistNameIdMap = getPopular.GetPopularArtists();
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
})
However the result I got is
outside
Promise { {} }
inside
It seems like the return was before the request gives back the information. I wonder what should I write to make sure that I can obtain the correct artistNameIdMap at playlist.js.
Though you've already accepted an answer, there are a couple of additional things I can add. First, the request() library has been deprecated and it is not recommended for new code. Second, there is a list of recommended alternatives here. Third, all these alternatives support promises natively as that is the preferred way to program asynchronous code in modern nodejs programming.
My favorite alternative is got() because I find it's interface simple and clean to use and it has the features I need. Here's how much simpler your code would be using got():
const got = require('got');
let artistNameIdMap = {};
async function getPopularArtists() {
const options = {
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
};
const url = CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath;
let results = await got(url, options).json();
// update local cache object
artistNameIdMap = getArtistNameIdMap(results, artistNameIdMap);
return artistNameIdMap;
}
module.exports = {
GetPopularArtists: getPopularArtists
}
Note: The caller should supply error handling based on the returned promise.
GetPopularArtists().then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
Since you want to use Promises, use it like this
const getPopularArtists = () => new Promise((resolve, reject) {
const options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: {
'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
json: true
}
request.get(options, (error, response, body) => {
if (error) {
reject(error);
} else if (response.statusCode === 200) {
console.log("inside");
resolve(getArtistNameIdMap(body, artistNameIdMap));
} else {
reject("get popular error");
}
});
});
module.exports = {
GetPopularArtists: getPopularArtists
}
And use it like
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", async (req, res) =>{
try {
const artistNameIdMap = await getPopular.GetPopularArtists();
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
} catch(err) {
res.send(err);
}
})
Alternatively, without promises, you'll need to use a callback
Using callbacks:
const getPopularArtists = (callback) => {
const options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
json: true
}
request.get(options, function(error, response, body) {
if (error) {
callback(error);
} else if (response.statusCode === 200){
console.log("inside");
callback(null, getArtistNameIdMap(body, artistNameIdMap));
} else {
callback("get popular error");
}
})
};
module.exports = {
GetPopularArtists: getPopularArtists
}
And use it like:
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", (req, res) =>{
getPopular.GetPopularArtists((err, artistNameIdMap) => {
if (err) {
// handle error here
} else {
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
}
});
});

Not getting data after dependent api call using async problem node

I am calling API to fetch data on the basis of that data I am calling different APIs which is based on condition.
I have used a promise to maintain the async code as well but no luck so far. At the end of the block, I want every data pushed inside array but I am getting a blank array.
async (body, nextCall) => {
var tmpArryOfModuleList = []
var bodyData = body.data
var promise = new Promise((resolve, reject) => {
bodyData.forEach(element => {
if (element.hasCRUD === '0') {
var options = {
method: 'GET',
url: `${apiURL}/api/fetchAllCharts`,
headers:
{
Authorization: token
}
};
request(options, function (error, response, dashboardData) {
if (error) {
return nextCall({
error: error
})
}
var parsedDashboardData = JSON.parse(dashboardData)
for (var i = 0; i < parsedDashboardData['data'].length; i++) {
var val = element.name + " - " + parsedDashboardData['data'][i]['name']
var randomID = Math.random().toString(36).slice(2)
tmpArryOfModuleList.push({ "_id": randomID, "submodule": val })
}
});
} else if (element.hasCRUD == '1') {
var options = {
method: 'GET',
url: `${apiURL}/api/fetchAllActions`,
headers:
{
Authorization: token
}
};
request(options, function (error, response, crudData) {
if (error) {
return nextCall({
error: error
})
}
var parsedcrudData = JSON.parse(crudData)
for (var i = 0; i < parsedcrudData['data'].length; i++) {
var val = element.name + " - " + parsedcrudData['data'][i]['name']
var randomID = Math.random().toString(36).slice(2)
tmpArryOfModuleList.push({ "_id": randomID, "submodule": val })
}
});
} else {
console.log('no data found')
reject('No Data Found')
}
})
resolve(tmpArryOfModuleList)
})
console.log('tmpArryOfModuleList', tmpArryOfModuleList)
}
What am I doing wrong? How can I achieve the result on the last array?

Request Params Node JS 500 Error

As the uri is generated is as expected and list data is shown in page but while sending the req in request method, 500 error occurs instead of retruning body.
uri: http://yufluyuinnepal.com/?vTRIPTYPE=O&vOPSID=O&vSTRFROM=KTM&vSTRFROMTXT=&vSTRTO=PKR&vSTRTOTXT=&vFLIGHTDATE=27-Nov-2018&vRETURNDATE=27-Nov-2018&vADULT=1&vCHILD=0&vNATIONALITY=NP&vNATIONALITYTXT=Nepal&
const uri = `http://yufluyuinnepal.com/?${queryString(query)}`;
console.log(uri);
const req = {
uri: uri,
};
request(req, (error, response, body) => {
if (error) {
return reject(error);
}
if (response.statusCode !== 200) {
return reject(new Error(`Expected 200 but got ${response.statusCode}`));
}
return resolve(body);
});
Let me know how can i return body and what is wrong in my code.
In Request npm module, specify what kind of request is it (GET/POST etc)
// Example GET Request
var options = {
method: "GET",
url:
uri,
headers:
{
// headers as per documentation
}
};
request(options, (error, response, body) => {
if(error){}
if(response.statusCode !== 200){}
return resolve(body);
})
This is your current implementation with a callback function.
const req = {
uri: uri,
method: 'GET'/'POST'
};
request(req, (error, response, body) => {
if (error) {
console.log(error);
}
if (response.statusCode !== 200) {
//Do something
}
console.log(body);
//Do something
});
When using request-promise module you should write something like this
var rp = require('request-promise');
const req = {
uri: uri,
method: 'GET'/'POST'
}
rp(req)
.then((res) => {
//Do something
})
.catch((error) => {
//Do something with error
});
Please try this
let requestp=require('request-promise');
var options = {
    method: 'POST',
    url: 'uri',
    resolveWithFullResponse: true,
    headers: {
                'Accept': 'application/json',
                'Content-Type' : 'application/json'
            },
            body: TextedValue
        };
     
        await  requestp(options).then(async function(Content){
           await requestp(options).then(async function(response){
                if (await response.statusCode == 200)
                    {
                        console.log(Content); // in ur case it is body
                    }
                 else
                    {
                        console.log("Response code "+response.statusCode+" .Try Again Later")
                   }
                })
           })

Node / Javascript - pipe writeStream / file to post request

I have the following code, it creates a file on a remote server from a test var (just to make sure it worked), but now I need to upload a file and I'm not sure how to actually attach it to the request, here is the code:
var dataString = '#test.txt';
var options = {
uri: 'https://site.zendesk.com/api/v2/uploads.json?filename=test.txt',
method: 'POST',
headers: {
'Content-Type': 'application/binary',
'Accept': 'application/json',
Authorization: 'Basic bXVydGV6LmF....'
},
body: dataString
//this will create a test file with some text, but I need
//to upload a file on my machine instead
}
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
var x = {
error: error,
response: response,
body: body
}
console.log(x);
}
request(options, callback);
I was thinking something in the lines of:
fs.createReadStream('text.txt').pipe({function?})
But I'm not sure how to finish this part unfortunately.
update: 2019
It's been a LONG time, but someone asked for the solution. I'm not sure if this is how I fixed it tbh or if this code even works, but I found this digging around, give it a try.
Also, Zendesk updated their API at some point, not sure when exactly so this may be old anyways:
var uploadAttachment = function() {
var uOptions = {
uri: 'xxx/api/v2/uploads.json?filename=' + fileName,
method: 'POST',
headers: {
'Content-Type': 'application/binary',
'Accept': 'application/json',
Authorization: 'Basic xxx'
}
};
function callback(error, response, body) {
if (!body) {
if (error) {
return next(error);
} else {
var x = {
error: true,
message: "Some message",
err: response
};
return next(x);
}
}
if (body && body.error) {
return next(error);
}
if (error) {
return next(error);
}
var jr = JSON.parse(body);
var uploaded = {};
if (jr.upload) {
uploaded = jr.upload;
}
attachToComment(uploaded);
}
fs.createReadStream(tempPath + fileName).pipe(request(uOptions, callback));
};
I hope this helps, sorry in advance if it does not work, I no longer have access to zendesk.

Categories

Resources