In node.js I'm using deasync to return the result of a request query.
var request = require('request');
var deasync = require("deasync");
const URL_1 = "...", URL_2 = "...", USER_AGENT = "...";
function getHtml() {
function requrl(url, form) {
return {
url: url,
headers: {'User-Agent': USER_AGENT},
form: form,
jar: true
}
}
var form = {email:"email#geemail.com", password:"thepass"};
var resp;
request.post(requrl(URL_1, form), function (error, response, body) {
if (error || response.statusCode != 200) {
resp = error;
} else {
request(requrl(URL_2), function (error, response, body) {
console.log(response); // <- this makes it work
if (error || response.statusCode != 200)
resp = error;
else
resp = body;
})
}
})
while (resp === undefined) deasync.runLoopOnce();
return resp;
}
This works fine. But if i remove this line: console.log(response); it never returns. I have no idea what is going on.
Related
I can be considered new to Node.JS so apologies, in here I am trying to make a function that yields code execution until the code finished making a HTTP request (using the "request" npm module) which then will be returned, the issue is that the library does not yield the code execution, I have tried using promise but it still won't yield code execution.
Original code:
const request = require("request")
// CONFIG
const ROBLOSECURITY = ""
var http_header = {
"Cookie": ".ROBLOSECURITY="+ROBLOSECURITY
}
function MakeRbxReq(http_method, url, payload) {
var jsonbody
var retfunc = {}
try {
jsonbody = JSON.stringify(payload)
} finally {}
var options = {
uri: "http://" + url,
body: jsonbody || "",
methpd: http_method,
headers: http_header
}
request(options, function(_, res) {
if (http_method.toUpperCase() == "POST" || http_method.toUpperCase() == "PUT" || http_method.toUpperCase() == "PATCH" || http_method.toUpperCase() == "DELETE") {
if (res.headers["X-CSRF-TOKEN"]) {
http_header["X-CSRF-TOKEN"] = res.headers["X-CSRF-TOKEN"]
options["headers"] = http_header
if (res.statusCode == 403) {
request(options, function(_, res) {
retfunc = {statusCode: res.statusCode, body: res.body}
})
} else {
retfunc = {statusCode: res.statusCode, body: res.body}
}
}
}
retfunc = {
statusCode: res.statusCode,
body: res.body
}
return
})
return retfunc
}
console.log(MakeRbxReq("GET", "search.roblox.com/catalog/json?CatalogContext=2&Subcategory=6&SortType=3&SortAggregation=5&Category=6"))
Promise attempt:
const request = require("request")
// CONFIG
const ROBLOSECURITY = ""
var http_header = {
"Cookie": ".ROBLOSECURITY="+ROBLOSECURITY
}
function MakeRbxReq(http_method, url, payload) {
var jsonbody
var retfunc = {}
try {
jsonbody = JSON.stringify(payload)
} finally {}
var options = {
uri: "http://" + url,
body: jsonbody || "",
methpd: http_method,
headers: http_header
}
async function req() {
let reqPromise = new Promise(function(resolve, reject) {
request(options, function(err, res) {
console.log("resolving")
resolve({statusCode: res.statusCode, body: res.body})
})
})
}
req()
return retfunc
}
console.log(MakeRbxReq("GET", "search.roblox.com/catalog/json?CatalogContext=2&Subcategory=6&SortType=3&SortAggregation=5&Category=6"))
Output from using promise:
C:\Program Files\nodejs\node.exe .\index.js
{}
resolving
request (promise) is asynchronous.
You should work with await or then
Here are some examples
For some reason, in node.js, the code is not running in order. It is running the console.log(data2) before even retrieving the data from function2.
I am assuming it is because node.js runs asynchronously. However, I am not too sure how to fix it.
Thanks for all the help in advance
function function1(app){
app.post('/test', (req, res, next) => {
const url = `url1`;
request(url, function(error, response, body) {
if(!error && response.statusCode == 200) {
var data = JSON.parse(body);
var data2 = function2(data.id);
console.log(data2); //undefined
res.send(profileData);
}
});
})
}
function function2(id){
const url = `url2/${id}`;
request(url, function(error, response, body) {
if(!error && response.statusCode == 200) {
var data = JSON.parse(body);
console.log(data); //output correct data
return data;
}
});
}
function function1(app){
app.post('/test', (req, res, next) => {
const url = `url1`;
request(url, async function(error, response, body) {
if(!error && response.statusCode == 200) {
var data = JSON.parse(body);
var data2 = await function2(data.id);
console.log(data2); //undefined
res.send(profileData);
}
});
})
}
function function2(id) {
const url = `url2/${id}`;
return new Promise(function (resolve, reject) {
request(url, function(error, response, body) {
if(!error && response.statusCode == 200) {
resolve(JSON.parse(body));
} else {
reject(error);
}
});
});
}
Because you're calling function2() just before outputting console.log(data2). The latter gets executed immediately, while the former has to make a server request. Pass data2 to function2() instead and output it after you output the result from function2()
function function1(app){
app.post('/test', (req, res, next) => {
const url = `url1`;
request(url, function(error, response, body) {
if(!error && response.statusCode == 200) {
var data = JSON.parse(body);
var data2 = function2(data.id, data2);
res.send(profileData);
}
});
})
}
function function2(id, data2){
const url = `url2/${id}`;
request(url, function(error, response, body) {
if(!error && response.statusCode == 200) {
var data = JSON.parse(body);
console.log(data); //output correct data
console.log(data2); //undefined
return data;
}
});
}
Firstly, I'm sorry if this has been posted before. I searched but couldn't find any credible solution.
So I'm working on this route in nodejs where I make an API call for a piece of information and then using that info in an if statement to check if it's the correct info(the server sometimes sends wrong info).
If I get the correct info then I use that in another API to get more info about it and render it into my template. Everything works fine.
But I want the first API call to take place again if the info doesn't match or it's wrong. How can I initiate the API call again from the start(like a loop) and it will break only if the info is correct. Please check the "comment" in the code below. That is where I don't know what to put. Your help would be highly appreciated.
PS. I am a beginner in nodejs and javascript.
Route
router.get("/check", (req, res) => {
if(req.query.search) {
var input = req.query.search;
var url = "http://firstapi.com/json/" + input + "?fields=query";
request(url, function(error, response, body) {
if(!error && response.statusCode === 200) {
var data = JSON.parse(body);
if(data.query.match(/((^|\.)((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]?\d))){4}$/)){
var url = "https://secondapi.com/" + data.query + "?key=something";
request(url, function(error, response, body) {
if(!error && response.statusCode === 200) {
var Data = JSON.parse(body);
res.render("index", {data: Data});
}
});
}else{
//want to use the input at the top and check the firstapi again. All the code above should run again until its the correct one which I will use in my template.
}
}
});
}else{
res.render("index", {data: null});
}
});
I would probably do it this way:
router.get('/check', (req, res) => {
if (req.query.search) {
var input = req.query.search;
// Put this logic away in a `checkData` function
checkData(input)
.then(data => {
res.render('index', { data }); // Short version of {data: data}
})
.catch(err => {
console.error(err);
res.render('index', { data: null });
});
} else {
res.render('index', { data: null });
}
});
// Here, we have a `retries` parameter, set to 0 initially
function checkData (input, retries = 0) {
const maxRetries = 3;
// Return a promise (you could also use callbacks)
return new Promise((resolve, reject) => {
// Define a retry method
const retry = () => {
if (retries < maxRetries) {
// Increment the retries count and go for another try
checkData(input, retries + 1).then(resolve).catch(reject);
} else {
reject(`Could not get the data after ${retries} retries.`);
}
};
var url = `http://firstapi.com/json/${input}?fields=query`;
request(url, function (error, response, body) {
if (!error && response.statusCode === 200) {
var data = JSON.parse(body);
if (data.query.match(/((^|\.)((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]?\d))){4}$/)) {
var url = 'https://secondapi.com/' + data.query + '?key=something';
request(url, function (error, response, body) {
if (!error && response.statusCode === 200) {
var Data = JSON.parse(body);
// If it worked, resolve with the data
resolve(Data);
} else {
retry();
}
});
} else {
retry();
}
}
});
});
}
I have a modified code in react-native for fetching data with server, that works fine. I want to add NetInfo to always check before fetching if telephone has connection to internet. Is it posible inside promise? How to connect this async function to my code?
'use strict';
var MAX_WAITING_TIME = 30000
var processStatus = function (response) {
// status "0" to handle local files fetching (e.g. Cordova/Phonegap etc.)
if (response.status === 200 || response.status === 0 || response.status === 201 || response.status === 422 || response.status === 302 ) {
return Promise.resolve(response)
} else if(response.status === 413) {
return Promise.reject(alert(____mobile.connection_error.large_file))
} else {
//return Promise.reject(alert("Process status: "+JSON.stringify(response )))
return Promise.reject(alert(____mobile.connection_error.top));
console.log("Process status: "+JSON.stringify(response ));
}
};
var parseJson = function (response) {
return response.json();
};
var getWrappedPromise = function () {
var wrappedPromise = {},
promise = new Promise(function (resolve, reject) {
wrappedPromise.resolve = resolve;
wrappedPromise.reject = reject;
});
wrappedPromise.then = promise.then.bind(promise);
wrappedPromise.catch = promise.catch.bind(promise);
wrappedPromise.promise = promise;// e.g. if you want to provide somewhere only promise, without .resolve/.reject/.catch methods
return wrappedPromise;
};
/* #returns {wrapped Promise} with .resolve/.reject/.catch methods */
var getWrappedFetch = function () {
var wrappedPromise = getWrappedPromise();
var args = Array.prototype.slice.call(arguments);// arguments to Array
fetch.apply(null, args)// calling original fetch() method
.then(function (response) {
wrappedPromise.resolve(response);
}, function (error) {
// wrappedPromise.reject(alert("Fetch status: " + error));
wrappedPromise.reject(____mobile.connection_error.top);
console.log("Fetch status: " + error);
})
.catch(function (error) {
wrappedPromise.catch(error);
});
return wrappedPromise;
};
/**
* Fetch JSON by url
* #param { {
* url: {String},
* [cacheBusting]: {Boolean}
* } } params
* #returns {Promise}
*/
var postJSON = function (params) {
var headers1 = {}
if (params.json){
headers1 = {
'Accept': 'application/json',
'Content-Type': 'application/json'}
}
if (params.headersIn){
headers1 = params.headersIn
}
var methodTmp = 'POST'
if (params.methodIn) {
methodTmp = params.methodIn
}
console.log(methodTmp)
var wrappedFetch = getWrappedFetch(
params.cacheBusting ? params.url + '?' + new Date().getTime() : params.url,
{
method: methodTmp,//'POST',// optional, "GET" is default value
headers: headers1,
body: params.send_data
});
var timeoutId = setTimeout(function () {
wrappedFetch.reject(alert(____mobile.connection_error.timeout, ____mobile.connection_error.check_connection));// reject on timeout
}, MAX_WAITING_TIME);
return wrappedFetch.promise// getting clear promise from wrapped
.then(function (response) {
clearTimeout(timeoutId);
return response;
})
.then(processStatus)
.then(parseJson);
};
module.exports = postJSON;
What would be the bast way to implement: NetInfo.isConnected.fetch() so fetched would only worked when there is internet connection?
EDIT:
I want to use:
NetInfo.isConnected.fetch()
Yeah I have to rewrite this code, not to use getWrappedPromise and now I think is good time for it.
EDIT2: Ok I refactored this code fragment, hope its better. Any comments welcome. I tested and I'm not sure if I still need this NetInfo.isConnected.fetch(). Now there is no errors where there is no connection or am I missing something?
New code:
var processStatus = function (response) {
if (response == undefined) {
return null
}
// status "0" to handle local files fetching (e.g. Cordova/Phonegap etc.)
if (response.status === 200 || response.status === 0 || response.status === 201 || response.status === 422 || response.status === 302 ) {
return Promise.resolve(response)
} else if(response.status === 413) {
return Promise.reject(alert(____mobile.connection_error.large_file))
} else {
//return Promise.reject(alert("Process status: "+JSON.stringify(response )))
console.log("Process status: "+JSON.stringify(response ));
return Promise.reject(alert(____mobile.connection_error.top));
}
};
var parseJson = function (response) {
if (response == undefined) {
return null
}
return response.json();
};
var postJSON = function (params) {
var headers1 = {}
if (params.json){
headers1 = {
'Accept': 'application/json',
'Content-Type': 'application/json'}
}
if (params.headersIn){
headers1 = params.headersIn
}
var methodTmp = 'POST'
if (params.methodIn) {
methodTmp = params.methodIn
}
console.log(methodTmp)
var fetchPromise = fetch(params.cacheBusting ? params.url + '?' + new Date().getTime() : params.url,
{
method: methodTmp,//'POST',// optional, "GET" is default value
headers: headers1,
body: params.send_data
})// calling original fetch() method
.then(function (response) {
return response;
}, function (error) {
console.log("Fetch status: " + error);
return fetch
}).then(processStatus)
.then(parseJson);
// timeoutId = setTimeout(function () {
// wrappedFetch.reject(alert(____mobile.connection_error.timeout, ____mobile.connection_error.check_connection));// reject on timeout
// }, MAX_WAITING_TIME);
return fetchPromise
};
I have a list of tags that I need to extract. the list is called list.
I'm trying to find all 'og:*' meta that correspond to the list and are available in a fetched html. Then I need to return a hash to the user in JSON that contains these meta tags. But the process method return undefined rather than the hash.
var http = require('http');
var url = require('url');
var request = require('request');
var jsdom = require("jsdom");
var fs = require('fs');
var cssom = require('cssom');
var list = ['title', 'description']; //here the og-tags I need to extract
var meta = {};
function process(url) {
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
jsdom.env({
html: body,
scripts: [
'http://code.jquery.com/jquery-1.5.min.js'
],
done: function(errors, window) {
var $ = window.$;
$('meta[property^="og:"]').each(function() {
for (var element in list) {
if ($(this).attr('property') == 'og:' + list[element]) {
meta[list[element]] = $(this).attr('content');
// this works well, if I do console.log(meta), I get the hash correctly filled.
}
}
});
}
});
}
});
return meta; // this is where the probleme is. This return undefined.
}
http.createServer(function (request, response) {
request.setEncoding('utf8');
response.writeHead(200, {'Content-Type': 'text/plain'});
process(url.parse(request.url, true).query['content'], function(result) {
console.log(result); // prints no result
});
response.end();
}).listen(8124);
console.log('Server running at http://0.0.0.0:8124');
Because request is asynchronous, you need to make process asynchronous as well. That means having process accept a callback parameter that it will call once meta is available. As it is now, process is returning meta before the request callback populates it.
function process(url, callback) {
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
jsdom.env({
html: body,
scripts: [
'http://code.jquery.com/jquery-1.5.min.js'
],
done: function(errors, window) {
var $ = window.$;
$('meta[property^="og:"]').each(function() {
for (var element in list) {
if ($(this).attr('property') == 'og:' + list[element]) {
meta[list[element]] = $(this).attr('content');
callback(null, meta);
}
}
});
}
});
} else {
callback(error);
}
});
}
http.createServer(function (request, response) {
request.setEncoding('utf8');
response.writeHead(200, {'Content-Type': 'text/plain'});
process(url.parse(request.url, true).query['content'], function(error, result) {
console.log(result); // prints no result
});
response.end();
}).listen(8124);