I do have an issue when I want to decorate my export with a wrapper.
I have a wrapper/hof function that encapsulate the real function like this:
import { withSth } from './anotherFile'
import { someConst } from './someConst'
const myFunc = () => {}
export {
myFunc: withSth(someConst, myFunc)
}
Parsing error: ',' expected.
This does not work while this work:
import { withSth } from './anotherFile'
import { someConst } from './someConst'
const myFunc = () => {}
module.exports = {
myFunc: withSth(someConst, myFunc)
}
The only way i can do this is like this:
import { withSth } from './anotherFile'
import { someConst } from './someConst'
const myFuncX = () => {}
const myFunc = withSth(someConst, myFuncX)
// OR
// const myFync = withSth(someConst, () => {})
// but it lose readability
module.exports = {
myFunc
}
My point is how can I do the same thing with export and without using default export and renaming all my function
module.exports = {
methodA: withSth(param, methodA),
methodB: withSth(param, methodB),
methodC: withSth(param, methodC),
methodD: withSth(param, methodD),
}
Unlike Commonjs modules (with module.exports), ES6 modules do not export values but variable bindings. You must declare a variable1, you cannot export something unnamed. So your choices are only
export const myFunc = withSth(someConst, myFuncX);
const myFuncX = () => {};
export const myFync = withSth(someConst, () => {});
const myFuncX = () => {};
const myFyncY = withSth(someConst, () => {});
export { myFuncY as myFunc }
1: with the exception of export default …;, which implicitly declares a variable with an unforgeable name for you. But you want multiple named exports.
Related
I want to export default all functions inside export default, but every time I try to import them in another file, I get the error that the functions don't exists. Am I importing wrong?
export default () => {
// methods
const makeRequest = async () => {
async function useAllBenefits() {
...
return payload;
}
async function useTopBenefits() {
...
return payload;
}
// exposed
return {
useAllBenefits,
useTopBenefits,
makeRequest
};
};
}
myotherfile.js
import all from '../myFile'
console.log(all.useAllBenefits)
Don't put them inside another function
Use the export keyword
Such:
export const aFunction = () => {};
export const anOtherFunction = () => {};
const someDefaultExport = () => {};
export default someDefaultExport;
Then you can import them:
import theDefault, { aFunction, anOtherFunction } from "../myFile";
If you want to export multiple functions AS DEFAULT you can do it by exporting one object whose properties are functions.
export default {
function1: () => {},
function2: () => {},
function3: () => {}
}
Now in another file you can import them and use as bellow:
import all from '../myFile.js';
all.function1();
all.function2();
Method 1. export each functions
myFunction.js
export const sum = (a,b) {
return a + b;
}
export const multiply = (a,b) {
return a * b;
}
Method 2.
myFunction.js
const sum = (a,b) {
return a + b;
}
const multiply = (a,b) {
return a * b;
}
export default {sum, multiply}
Import section
file.js
import all from './myFunction.js'
all.sum(10, 11);
Or
file.js
import {sum, multiply} from './myFunction.js'
sum(10, 11);
I'm trying to export an object directly, but I'm not getting the results I'd like;
const cmd = {
name: "testFunc",
desc: "Test",
execute(name, args) {
console.log("Test ()");
}
}
export {cmd}
I import it as follows;
import(`./commands/${file}`).then(cmd => {
console.log(cmd.cmd.name);
})
But I would rather be able to just do cmd.name, rather than cmd.cmd.name.
Don't export an object, use individual named exports instead:
export const name = testFunc";
export const desc = "Test";
export function execute(name, args) {
console.log("Test ()");
}
Alternatively, change your import statement to use destructuring:
import(`./commands/${file}`).then(({cmd}) => {
console.log(cmd.name);
})
I am struggling to put best practises into action, converting an existing file for Cypress testing into a more appropriate format for exporting and importing.
Currently:
support-file.js
export const1 = () => cy.get('#someId1');
export const2 = () => cy.get('#someId2');
export const3 = () => cy.get('#someId3');
export function myFunct1() {
// Do something
}
export function myFunct2() {
// Do something
}
export function myFunct3() {
// Do something
}
file-where-used.js
import {
const1, const2, const3,
myFunct1, myFunct2, myFunct3
}
// usage of the consts/functs below
I have experimented with trying to get them into a format such that I do not have to import each separately, but I cannot figure it out... I thought, perhaps wrapping all as a class and exporting that, which does work but only when using a require rather than import... And I also found difficulty in exporting my const variables...
attempt
export const1 = () => cy.get('#someId1');
export const2 = () => cy.get('#someId2');
export const3 = () => cy.get('#someId3');
class myClass {
myFunct1() {
// Do something
}
myFunct2() {
// Do something
}
myFunct3() {
// Do something
}
}
module.exports = new myClass();
You can cut your issues up in several steps.
Custom Commands/functions
Firstly you are creating custom commands like this one:
export function() {
// Do something
}
By putting that function in the file cypress/support/commands.js you don't have to import it in the integration files, but you do have to rewrite is like this:
Cypress.Commands.add('myFunct1', function () {
// Do something
})
What you end up in the integration file is this:
cy.myFunct1()
Global variables
You are assigning global variables like this:
export const1 = () => cy.get('#someId1');
export const2 = () => cy.get('#someId2');
export const3 = () => cy.get('#someId3');
Start with rewriting them to be a constant:
const const1 = () => cy.get('#someId1');
const const2 = () => cy.get('#someId2');
const const3 = () => cy.get('#someId3');
You'll always need to import them one by one, but you can combine them as long as they are in one file. You could do so by importing them into the testfile like this:
import {const1, const2, const3} from '<FILE_DIRECTORY>'
Now they are available trough the whole testfile.
I am writing a client to talk to a server API in JavaScript. I have an OOP background but am trying to embrace modern EcmaScript.
So I started with this:
customerApi.js:
const baseUrl = "http://myapi";
export const getCustomers = () => { /* get customer code */ }
export const addCustomer = cust => {}
export const deleteCustomer = id => {}
All the functions use baseUrl.
Now I want to refactor so that the code that uses customerApi.js sets/passes in the baseUrl, and the only ways I have come up with are -
make it a class:
export default class customerApi {
constructor(baseUrl) {
this._baseUrl baseUrl;
}
}
Pass it into every method:
export const getCustomers = (baseUrl) => { /* get customer code */ }
export const addCustomer = (baseUrl,cust) => {}
export const deleteCustomer = (baseUrl,id) => {}
Wrap in a function:
const moduleFn = baseUrl => (
return {
getCustomers: () => { /* get customer code */ }
addCustomer: (cust) => {}
deleteCustomer: (id) => {}
}
)
export default moduleFn;
These are just examples.
What is the most common pattern to implement a "settable" variable on a module?
I would go with the function approach
export default function(baseUrl){
return Object.freeze({
getCustomers: () => { /* get customer code */ }
addCustomer: (cust) => {}
deleteCustomer: (id) => {}
})
}
This is because all the functions have closure on the baseUrl and no extra work is required.
Client code can simply
import yourmodule from 'yourmodule';
var derp = yourmodule('www.derp.com')
I have a few exported functions from ES6 module like:
export const funA = params => 'hello funA';
export const funB = params => 'hello funB';
I'd like to wrap them before exporting:
const wrapper = params => fun => {
// some extra logic
Object.assign(params, { extra: 'data' });
return fun(params);
};
export const funA = wrapper(params => 'hello funA');
export const funB = wrapper(params => 'hello funB');
It works this way, but I'm wondering if it's possible to define funA and funB without wrapper invocation in a way simmilar to:
import { mapValues } from 'lodash';
const wrapper = params => fun => {
// some extra logic
Object.assign(params, { extra: 'data' });
return fun(params);
};
const funA = params => 'hello funA';
const funB = params => 'hello funB';
export default mapValues({ funA, funB }, wrapper);
The issue with above snippet is that named exports are not used.
Can I achieve named exports with possibility to wrap them with wrapper middleware dynamically?
Where are you going to determine which wrapper middleware?
You could do something like
export const funA = middleware => params => 'funA'
export const funB = middleware => params => 'funB'
then at the callsite:
import { funA } from './module.js'
const funFunA = middleware(funA)
But this is sounding more and more like a case for function composition:
import { funA } from './module.js'
import { nextFun } from './other.js'
const funFunA = compose(nextFun, funA)
Depending on your needs it might also be worth your while using something like the Arrow monad
https://evilsoft.github.io/crocks/docs/crocks/Arrow.html
Edit:
const _funA = a => b
export const funA = (...args) => {
switch (currentMood) {
case 'saucy': return sauce(_funA(...args))
default: return _funA(...args)
}
If you want to avoid repeating wrapper in every line, you could use destructuring assignment and named export. However, this requires repeating { funA, funB, ..., funXYZ }.
import { mapValues } from 'lodash';
const wrapper = params => fun => {
// some extra logic
Object.assign(params, { extra: 'data' });
return fun(params);
};
let funA = params => 'hello funA';
let funB = params => 'hello funB';
let { funA, funB } = mapValues({ funA, funB }, wrapper);
export { funA, funB };