node.js - Use variables outside functions - node.js

I'm new to node.js, and I'm struggling with functions and variables.
let shops = ['shop-one', 'shop-two']
function getShops(shops){
shops.forEach(element => {
console.log(element)
const shop = element
});
}
function getUrl(shop){
console.log(shop)
}
getShops(shops)
getUrl(shop) // shop is not defined
How can I use variables from one function on the other function or outside the functions for further use?
Like in my example I would use the Shopname 'shop-one' from the forEach-Loop in function getShops to be used on the function getUrl or even outside any function.
I would be grateful for any help.

let shops = ['shop-one', 'shop-two'];
// An object to store urls that will look like
// {'shop-one': 'http://aurl4shop1.com', 'shop-two': 'http://aurl4shop2.com' }
let urls = {};
let json = [];
function getShops(shops){
shops.forEach(element => {
console.log(element);
const shop = element;
// The following line will set a property on the url object with the value of the url. The property name is the shop name.
url[shop] = getUrl(shop);
});
}
function getUrl(shop){
console.log(shop);
}
shops.forEach(shop => json[shop] = fetchJson(shop);
// At this point the json object should look like this:
// { 'shop-one': { /* some json */ }, 'shop-two': /* some json */ }

Related

How do I pass parameters to Apify BasicCrawler handleRequestFunction?

I'm trying to migrate an existing function to use it inside an Apify actor.
Originally, the function loads a given URL, reads its JSON response, and according to some supplied parameters, extracts some data and returns an object with results.
If you ask, it's not scraping anything "final" at this point. Its results are temporary and will be used to create other URLs which will be scraped then (with another crawler) for actual, useful results.
The current function that executes the crawler is something like this:
let url = new URL('/content', someBaseURL);
url.searchParams.set('search', someKeyword);
const reqList = new apify.RequestList({
sources: [ { url: url.toString() } ]
});
await reqList.initialize();
const crawler = new apify.BasicCrawler({
requestList: reqList,
handleRequestFunction: reqHandler
});
// How do I set the inputs for reqHandler() here ?
await crawler.run();
// How do I get the output from reqHandler() here ?
And the reqHandler code is something like this:
async function reqHandler(options) {
const response = await apify.utils.requestAsBrowser({
url: options.request.url
});
// How do I read parameters from the caller here ?
let searchResults = JSON.parse(response.body);
// ... result object creation logic goes here ...
// How do I return a result to the caller here ?
}
I am pretty new to this Apify thing and lost in the documentation.
Thanks for your help.
handleRequestFunction doesn't take any external input or produce any outputs. Simply use it as a closure and capture inputs from the surrounding code or you can wrap it in a different function.
Normally we do it like this:
const context = {}; // put your inputs here
const crawler = new apify.BasicCrawler({
requestList: reqList,
handleRequestFunction: async () => {
// use context here
// output data
await Apify.pushData(results);
}
});
EDIT: I forgot to mention a use-case on how to pass input. You need to do it via the request.userData object when adding to a queue or a list.
// The same userData is available in request list.
await requestQueue.addRequest({
url: 'https://example.com',
userData: { myInput: 'any-data' }
});
// Then in handleRequestFunction
handleRequestFunction: async (( request }) => {
const { myInput } = request.userData;
// ...
}

How can I store the value of a promise and use it once resolved?

I am currently developing an app which interacts with uniswap, and I have developed a Wrapper class to contain the info and variables I'll need about some pair (e.g DAI/WETH).
As some of this values are asynchronous, I have coded a build() async function to get those before calling the constructor, so I can store them. I want to store the result of this build function, which is an instance of the class I have defined, inside a variable to use it later, but I need to know whether the Promise that that build function returns is resolved before using it, so how can I make it?
Here is the code of the class:
'use strict'
const { ChainId, Fetcher, WETH, Route, Trade, TokenAmoun, TradeType, TokenAmount } = require('#uniswap/sdk')
const { toChecksumAddress } = require('ethereum-checksum-address')
const Web3 = require('web3')
const web3 = new Web3()
const chainId = ChainId.MAINNET;
let tok1;
let tok2;
let pair;
let route;
let trade;
class UniswapTokenPriceFetcher
{
constructor(async_params)
{
async_params.forEach((element) => {
if (element === 'undefined')
{
throw new Error('All parameters must be defined')
}
});
this.trade = async_params[0];
this.route = async_params[1];
this.pair = async_params[2];
this.tok1 = async_params[3];
this.tok2 = async_params[4];
}
static async build(token1, token2)
{
var tok1 = await Fetcher.fetchTokenData(chainId, toChecksumAddress(token1))
var tok2 = await Fetcher.fetchTokenData(chainId, toChecksumAddress(token2))
var pair = await Fetcher.fetchPairData(tok1, tok2)
var route = new Route([pair], tok2)
var trade = new Trade(route, new TokenAmount(tok2, web3.utils.toWei('1', 'Ether')), TradeType.EXACT_INPUT)
return new UniswapTokenPriceFetcher([trade, route, pair, tok1, tok2])
}
getExecutionPrice6d = () =>
{
return this.trade.executionPrice.toSignificant(6);
}
getNextMidPrice6d = () =>
{
return this.trade.nextMidPrice.toSignificant(6);
}
}
module.exports = UniswapTokenPriceFetcher
Thank you everybody!
EDIT: I know Uniswap only pairs with WETH so one of my token variables is unneccesary, but the problem remains the same! Also keep in mind that I want to store an instance of this class for latter use inside another file.
You should either call the build function with await
const priceFetcher = await UniswapTokenPriceFetcher.build(token1, token2)
or followed by then
UniswapTokenPriceFetcher.build(token1, token2).then(priceFetcher => {...})
I don't see any other way.

Calling a method within a dynamically named object

I am trying to invoke a method of a dynamically named object.
I have a few objects each containing a method named 'getWeight'. I need to invoke this method of a subset of these objects. However, the subset of objects depends on user inputted info, which is why I'm attempting to dynamically construct the object name and invoke it's 'getWeight' method within a loop.
My code is below:
// Importing objects containing 'getWeight' method
const Apple = require('../classses/Apple');
const Pear = require('../classes/Pear);
const Carrot = require('../classes/Carrot);
const Potato = require('../classes/Potato);
const promises = {};
const user = 'userX'; // This is the inputted info, could also equal 'userY'.
const searchableFoods = {
userX: ['Apple', 'Pear'],
userY: ['Carrot', 'Potato']
};
for (i = 0; i < searchableFoods[user].length; ++i) {
promises[searchableFoods[user][i]] = new Promise(function(resolve, reject) {
// Below line should behave like: Apple.getWeight(arg1, function....
searchableFoods[user][i].getWeight(arg1, function(response) {
resolve(response);
})
})
}
Unfortunately, I get this error:
[searchableFoods[user][i].getweight] is not a function
I've tried a number of variations but can't make it work. Is it possible to do this?
Require all of those into a single object rather than many standalone variables, and then you can use simple property lookup to get to the appropriate requireed value. Also, forEach will likely result in more readable code, and you can pass the function name alone (resolve) rather than defining an extra anonymous function for the getWeight callback:
const foods = {
Apple: require('../classses/Apple'),
Pear: require('../classes/Pear),
Carrot: require('../classes/Carrot),
Potato: require('../classes/Potato)
};
// ...
searchableFoods[user].forEach((foodName) => {
promises[foodName] = new Promise((resolve) => {
foods[foodName].getWeight(arg1, resolve);
});
});
Can you define array not using strings? Something like that?
const searchableFoods = {
userX: [Apple, Pear],
userY: [Carrot, Potato]
};
You're trying to access getWeight as a property of string 'Apple' and not of the actual object Apple that you are importing.
Change the subset array to something like this
const searchableFoods = {
userX: [Apple, Pear],
userY: [Carrot, Potato]
};
Which makes the final code to be
const Apple = require('../classses/Apple');
const Pear = require('../classes/Pear);
const Carrot = require('../classes/Carrot);
const Potato = require('../classes/Potato);
const promises = {};
const user = 'userX' // This is the inputted info, could also equal 'userY'.
const searchableFoods = {
userX: [Apple, Pear],
userY: [Carrot, Potato]
};
for (i = 0; i < searchableFoods[user].length; ++i) {
promises[searchableFoods[user][i]] = new Promise(function(resolve, reject) {
// Below line should behave like: Apple.getWeight(arg1, function....
searchableFoods[user][i].getWeight(arg1, function(response) {
resolve(response);
})
})
}

i have already tried,but i don't no how to call the function in another file

sir/madam exlain the flow of node.js from client to server with the dynamic parameters passing from userinterface to api's based up on these parameters we will get the output from api.for example sabre api etc..
exports.flightDestinations = function(req, res) {
var callback = function(error, data) {
if (error) {
// Your error handling here
console.log(error);
} else {
// Your success handling here
// console.log(JSON.parse(data));
res.send(JSON.parse(data));
}
};
sabre_dev_studio_flight.airports_top_destinations_lookup({
topdestinations: '50'
}, callback);
};
we want this value 50 from user...and how to give this value?and how to call this function in node.js.
The exports variable is initially set to that same object (i.e. it's a shorthand "alias"), so in the module code you would usually write something like this:
var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;
to export (or "expose") the internally scoped functions myFunc1 and myFunc2.
And in the calling code you would use:
var m = require('mymodule');
m.myFunc1();
where the last line shows how the result of require is (usually) just a plain object whose properties may be accessed.
NB: if you overwrite exports then it will no longer refer to module.exports. So if you wish to assign a new object (or a function reference) to exports then you should also assign that new object to module.exports
It's worth noting that the name added to the exports object does not have to be the same as the module's internally scoped name for the value that you're adding, so you could have:
var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required
followed by:
var m = require('mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

hogan.js how to debug a variable

i'm very familiar with the javascript console.log(), and the php_dump() functions that allows us to see what's in a variable, i want to know if there is some function like this in hogan.js that let us inspect the content of a variable.
add some method to your data and include it at the loctation you need to inspect the scope
var data = {
...
// your vars,
...
inspect: function () {
return function () {
console.log(this);
}
}
};
template.render(data);
anywhere you use {{inspect}} it will log the current render context in the console
I slightly modified it to add the function to the data packet that is passed to Hogan in a centralized position, which, in my code, is a function called render().
Thank you for this clever trick.
function render(template, data, destination) {
data.inspect = function() {
return function() {
console.log("inspect:")
console.log(this);
};
};
// localized strings
data.strings = app.strings;
var tmpl = Hogan.compile(template);
var content = tmpl.render(data);
document.querySelector(destination).innerHTML = content;
}

Resources