Can something act both as an object and a function in JS? - javascript

I'm trying to create a programmatic interface to my api, I have the following routes
'api/location/:locationId/users' get, post
'api/location/:locationId/users/:userId' get, post, put
I would like to to use it like this
var myApi = new API('baseUrl');
myApi.api.location(locationId).users.get()
myApi.api.location(locationId).users.post(data)
myApi.api.location(locationId).users(userID).get()
myApi.api.location(locationId).users(userID).post(data)
myApi.api.location(locationId).users(userID).put(data)
so I started writing the class and realized it's not straight forward
class API{
constructor(baseUrl) {
this.axios = axios.create({ baseURL });;
}
this.api = {
location: (locationId) => {
users: ...(stuck)
}
}
}
I know there's different ways of doing it, but I am wondering if it's "possible" to have something act both as a function and object in javascript
ie.
var a = ..?..
a(blah) // returns an output
a.get(blah) // returns an output

It certainly is possible:
var myObj = {
someFunc: () => "foo"
}
myObj.someFunc.bar = "baz";
console.log(myObj.someFunc());
console.log(myObj.someFunc.bar);
Functions are objects just like almost everything else in JavaScript. That means you can add properties to them.

Got it. thanks #Cerbrus
class API {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.api = {
location: (locationId) => ({
users: (() => {
var a = (userId) => ({
get: () => `${this.baseUrl}/api/location/${locationId}/users/${userId}`
})
a.get = () => `${this.baseUrl}/api/location/${locationId}/users`;
return a
})()
})
}
}
}
var myApi = new API('baseUrl');
myApi.api.location('locationId').users.get()
// "baseUrl/api/location/locationId/users"
myApi.api.location('locationId').users('userId').get()
// "baseUrl/api/location/locationId/users/userId"

Related

Variable.map is not a function React Javascript

I am working on app and I am trying to extract three attributes of this string (I thought it was an array of objects is filteredResultsJSON, but it is a string) :
Well, when I want to get the news of a given section I am using this code:
export default function getNewsFilteredBySection (sectionSearched="") {
const URL= `https://api.nytimes.com/svc/mostpopular/v2/viewed/7.json?api-key=${API_KEY}`;
return fetch(URL)
.then(res=>res.json())
.then(response=> {
const { data = [] } = response;
if(Array.isArray(data)){
const {results} = response;
const filteredResults = results.filter(obj => {
return obj.section === sectionSearched;
});
const filteredResultsJSON = JSON.stringify(filteredResults);
const name = typeof(filteredResultsJSON);
console.log(name);
return filteredResultsJSON;
}
})
};
I did JSON.stringify(filteredResults) because I saw it when doing console.log()as an [Object Object] and I wanted to be able to read the information and to loop through it to be able to extract it.
So I am using this code to extract the attributes I want for each news:
export function getNewsAttributes (filteredResultsJSON=[]) {
const newsAttributes = filteredResultsJSON.map(filteredResultJSON=>{
const { title, abstract, url } = filteredResultJSON;
console.log(title, abstract, url);
return {title, abstract, url};
});
return newsAttributes;
};
But it returns the following error:
I have been researching and I totally think the matter is about JSON.Stringify(filteredResults). How could I maintain that variable as an object, being able to read it and extract the information from it?
I am going to use it like this, after an onClick event:
function showEvent (e) {
const sectionSearched = e.target.innerText;
const filteredResultsJSON = getNewsFilteredBySection(sectionSearched);
const newsAttributes = getNewsAttributes(filteredResultsJSON);
}
Thanks a lot :)
I solved it with this code:
export default function getNewsFilteredBySection (sectionSearched="") {
const URL= `https://api.nytimes.com/svc/mostpopular/v2/viewed/7.json?api-key=${API_KEY}`;
return fetch(URL)
.then(res=>res.json())
.then(response=> {
const { data = [] } = response;
if(Array.isArray(data)){
const {results} = response;
const filteredResults = results.filter(obj => {
return obj.section === sectionSearched;
});
console.log(filteredResults);
return filteredResults;
}
})
};
Finally I didnt need to do JSON.Stringify(filteredResults). However I am having this two errors and I dont know why, my app works:
Any idea? Thanks a lot :)
You need to add async
export default async function getNewsFilteredBySection (sectionSearched=""){ ...
showEvent = async (e) => { ...
and await
const filteredResultsJSON = await getNewsFilteredBySection(sectionSearched);

Instanceof 'Class' return false using a mock object

I'm testing a method and I need to use a mock object as parameter (I am using typemoq). The problem is that the instanceof check, always return false. How can I solve?
public foo(container: BaseClass): string {
if (container instanceof Application) { // Always returns false when I use a mock of the object
// do something
} else {
// do something else
}
return retval;
}
In my spec.ts
context('foo', () => {
it('should return...', () => {
const container = Mock.ofType<Application>();
const result = class.foo(container.object);
});
});
I tried this too, but the result is the same.
context('foo', () => {
it('should return...', () => {
const application = new Application();
const container = Mock.ofInstance(application);
const result = class.foo(container.object);
});
});
How can I fix this? I need to test what append when the parameter is an instance of 'Application'.
Thank you.
I have found a solution. Just change .object in .target in the tests.
context('foo', () => {
it('should return...', () => {
const application = new Application();
const container = Mock.ofInstance(application);
const result = class.foo(container.target); // instead of .object
});
});
In this way it is possible to mock the methods of 'Application' class and the 'instanceof Class' will return true

jest test async class method

class person {
constructor() {
...
}
fetchPersonData() {
fetch(api).then((return response) => {
return response;
})
}
async initializePerson() {
const data = await fetchPersonData();
}
}
I'm trying to write a test for initializePerson function but it doesn't get called.
test("pass initializePerson", async( ) => {
const personInstance = new person();
let spy = jest.spyOn(personInstance, "initializePerson").mockImplementationOnce(async () => {
return mock;
});
await personInstance.initializePerson();
expect(spy).toBeCalledTimes(1);
});
There are few mistakes.
(return response) is wrong.
You're spying the method which you're calling. It doesn't make any sense. Spy methods which you've used inside the methods before calling the actual method.
I think you're looking for something like this.
class Person {
constructor() {...}
fetchPersonData() {
return fetch(api).then(response => response.json())
}
async initializePerson() {
const data = await fetchPersonData();
}
}
and test.js
test("pass initializePerson", async () => {
const personInstance = new Person();
const fetchPersonDataSpy = jest.spyOn(personInstance, "fetchPersonData").mockResolvedValue({...})
await personInstance.initializePerson();
expect(fetchPersonDataSpy).toBeCalledTimes(1);
});
If you want test the other method and mock the fetch, read this article. This will help you!

Javascript function return object which contains 3 function defination but IntelliSense is not working for that return type

I have written a Logger function in javascript and that is a singleton function, from that function I am returning an object that contains the definition of the two functions, So when I am creating an object of that class I get the returned object contains function definition, and when I want to call something on that returned value my code IntelliSense is not working, can anybody help me with the IntelliSense. Also sharing the code. I am getting the IntelliSense for the getInstance method, but when i wan to use obj.setDebug I am not getting any code suggestion or IntelliSense for that part.
That Obj.isDebug autocomplete i am not getting
const Logger = () => {
let instance = null
_isDebug = false
let setDebug = (value = false) => {
_isDebug = value
}
let isDebug = () => {
return _isDebug
}
createInstance = () => ({
setDebug,
isDebug,
log
})
return {
getInstance: () => {
if (!instance) {
instance = createInstance()
}
return instance
}
}
}
const Log = Logger()
const obj = Log.getInstance();
console.log(obj.setDebug())
console.log(obj.isDebug())
Do getInstance automatically while defining Log, it'll be more simple:
const Logger = () => {
// Set app
const app = {
// Set _isDebug option
_isDebug: false,
// Set setDebug method
setDebug: (value = false) => app._isDebug = value,
// Get isDebug method
isDebug: (value = false) => app._isDebug
};
return app;
}
const Log = Logger();
Log.setDebug(true);
console.log(Log.isDebug());
Example is here
If you need more complex function with separate getInstance method, just follow the logic and feel free to add as much additional layers as you need... Below code is just for example. In given context it is pointless as I've mentioned before:
const Logger = () => {
// Set app
const app = {
// Set _isDebug option
_isDebug: false,
// Set isDebug method
setDebug: (value = false) => app._isDebug = value,
// Get isDebug method
isDebug: (value = false) => app._isDebug
};
// Initiator
const initiator = {
// Set init status var
instance: false,
// Set getInstance method
getInstance: () => {
if(!initiator.instance) initiator.instance = app;
return initiator.instance;
}
}
return initiator;
}
const Log = Logger();
const obj = Log.getInstance();
obj.setDebug(true);
console.log(obj.isDebug());
Example is here

node.js async return value & export module

I am trying to get some data from csv file, then make some magic with them and create an object with this derived data.
I created this function by using module.exports I exported it.
var csvtojson = require('csvtojson');
var data = [];
module.exports = function createStock(name){
var myObj = {};
csvtojson().fromFile('./csv-raw/'+name+'.csv')
.then(source => {
source.forEach(value => {
var row = {};
row.Date = value.Date;
row.Dividend_Yield = value.Dividend_Yield;
row.Gross_Dividend_Per_Share = value.Gross_Dividend_Per_Share;
row.Distribution_Rate = value.Distribution_Rate;
data.push(row);
});
})
.then(() => {
myObj = {
name: name,
data: data,
summary: {a: Math.random(), b: Math.random(), c: Math.random()}
};
})
.then(() => {
console.log(myObj)
return myObj
})
}
And import to the route;
const createdStock = require('../../modified');
router.get('/new/:stockName', async (req,res) => {
var stock = await createdStock(req.params.stockName);
setTimeout(() => {
console.log(stock);
}, 2000);
(I can see the result of console.log(myObj) inside first file)
(I can not see console.log(stock); inside second file)
I tried to figure out the problem whether stems from async behavior of JS but could find any solution ?
Generally my question is how can I send data that is created inside of .then block to another JS file.
In your createStock function you need to return your call to csvtojson. That will return the Promise making the await work properly. Then you won't need the setTimeout and you can just console.log(stock).
module.exports = function createStock(name){
var myObj = {};
return csvtojson().fromFile('./csv-raw/'+name+'.csv')
...
};

Categories