Instantiating a new function no access to inner function - javascript

This is quite a frustrating issue I am stuck on. I am exporting a parent function with quite a rigid structure for the purpose of library mocking.
const responses = require("../responses/index.js");
function fetch (
first = "contactsMultiple",
second = "passwordFail",
third = "contactsMultiple") {
this.first = first;
this.second = second;
this.third = third;
this.iteration = 1;
this.fetch = () => {
let body;
switch (this.iteration) {
case 1 :
body = responses.contacts[this.first];
break;
case 2 :
body = responses.password[this.second];
break;
case 3 :
body = responses.contacts[this.third];
break;
default:
body = responses.contacts["contactsMultiple"];
break;
}
const response = {
status: 200,
statusText: "OK",
json: () => {
return body;
}
};
this.iteration++;
return response;
}}
module.exports = fetch;
I export this, then import it, create a new instance of the function so I can set properties that I wish to increment and also set via the construction of the function. But the code then expects a function called fetch.
I need to be able to call it like:
const Fetch = new fetch();
then pass Fetch into the existing classes.
If I log this new function I can see it has a fetch property of a type function. but I keep getting this.fetch is not a function.
What am I missing?
Many thanks

Related

Using object literals for my complex cases

Hey I was wondering if it is somehow possible to use a object literal in this case to clean up my switch statement.
export const getTravelInfo = () => {
const url = window.location.href;
switch (url as any) {
case url.includes('trips'):
return epicTrips;
case url.includes('mini-trips'):
return miniTrips;
case url.includes('sailing-trips'):
return sailingTrips;
default:
return epicTrips;
}
};
This is what I have so far, I am just not sure how or even if this is possible to pass in a function and loop over the url to determine what string is present in the url and then deliver that value to the user.
function getTravelInfo2 () {
const url = window.location.href;
var travel = {
'trips': epicTrips,
'mini-trips': miniTrips,
'sailing-trips': sailingTrips,
'default': epicTrips
};
return travel[url];
}
My solution was to First get what I need from the URL Via
const url = 'http://www.test.com/trips';
firstPart = url.split('/', -1)[-1];
getTravelInfo(firstPart);
const getTravelInfo = (type) => {
var travel = {
'trips': epicTrips,
'mini-trips': miniTrips,
'sailing-trips': sailingTrips,
'default': epicTrips
};
return (travel[type] || travel['default']);
}
Much cleaner and easier to execute and understand.

Can't determine issue with JS storeClient function and error thrown

I have created two async functions within my JavaScript Zapier step to parse a raw webhook. The two async functions center around storeClient to "get" and "set" values on Storage by Zapier. However, I get an error thrown. I have a screen shot from Zapier test sub-step. Due to the way Zapier returns on error, I can't see any of my console.log output.
What have I done wrong with the async functions?
// function to talk to Storage By Zapier to get a key
//
async function getStore(passKey) {
try {
const store = StoreClient(inputData.secret);
const data = await store.get(passKey);
console.log(`Here is the data from store: ${data}`);
return data;
} catch(error) {
console.log(`We hit an error: ${error}`);
}
}
// function to talk to Storage By Zapier to set a key and values
//
async function setStore(passKey, passTags) {
try {
const store = StoreClient(inputData.secret);
await store.setMany({'email': passKey, 'tags': passTags});
} catch(error) {
console.log(`We hit an error: ${error}`);
}
}
// for testing in editor
//
//var contactData = JSON.parse(raw);
// only when Storage By Zapier not available
//var inputData = JSON.parse(inputStore);
// pull in data from Zapier
//
var contactData = JSON.parse(inputData.raw);
//console.log(contactData);
//console.log(inputData.secret);
//var inputData = JSON.parse(inputData.testStore);
//console.log(inputData.tags);
//console.log(`inputData.tags: ${inputData.tags}`);
//
// create output object to pass back to zapier after processing webhook from AgileCRM
//
// receive raw webhook by parsing using built-in function
//
var output = new Object();
//console.log(`inputData.tags: ${inputData.tags}`);
var contactEventData, isValentus, isDoubleOptIn, isUpdate, contactTags, tagsDidntchange, storeTags, storeTagsArray, tagsEqualCount;
// set-up variables and init
//
isValentus = false;
isDoubleOptIn = false;
tagsDidntchange = false;
contactTags = new Array();
storeTagsArray = new Array();
tagsEqualCount = 0;
contactEventData = contactData.eventData;
// find out is this is an update to a contact
//
contactData.eventName === 'Contact is Updated' ? isUpdate = true : isUpdate = false;
// find out if the contact is:
// Valentus, Double Opt-in and save other tags
//
contactEventData.tags.forEach(function(contactTag) {
switch(contactTag) {
case 'Valentus':
isValentus = true;
break;
case 'Double_Opt_In':
isDoubleOptIn = true;
break;
default:
contactTags.push(contactTag);
}
})
// initialize all variables to be passed via output object to Zapier
// ---this is so that the subsequent steps in the zap have data for the variable
//
var contactEmailAddress = '-', contactFirstName ='-', contactLastName = '-', contactPhoneNumber = '-', contactSource = '-', contactValentusUSERID = '-', contactStatus = '-', contactPhoneCallType = '-', contactInvitedby = '-', contactInvitedByEmail = '-', contactInvitedByWebsiteUID = '-', contactInvitedByValentusUSERID = '-', contactValentusTeam = '-';
// process contact properties to get needed variable data by property name
//
contactEventData.properties.forEach(function(properties) {
let propertyName = properties.name;
let propertyValue = properties.value;
switch(propertyName) {
case 'email':
contactEmailAddress = propertyValue;
break;
case 'first_name':
contactFirstName = propertyValue;
break;
case 'last_name':
contactLastName = propertyValue;
break;
case 'phone':
contactPhoneNumber = propertyValue;
break;
case 'Source':
contactSource = propertyValue;
break;
case 'Valentus userid':
contactValentusUSERID = propertyValue;
break;
case 'Status':
contactStatus = propertyValue;
break;
case 'Phone call type':
contactPhoneCallType = propertyValue;
break;
case 'Invited by':
contactInvitedby = propertyValue;
break;
case 'Invited by email':
contactInvitedByEmail = propertyValue;
break;
case 'Invited by website UID':
contactInvitedByWebsiteUID = propertyValue;
break;
case 'Invited by Valentus userid':
contactInvitedByValentusUSERID = propertyValue;
break;
case 'company':
contactValentusTeam = propertyValue;
break;
}
})
// get storage by email address and compare tags
// and see if tags changed. if they changed, we don't
// want to process any further
//
//storeTags = inputData.tags;
getStore(contactEmailAddress).then(data => {
console.log(data);
storeTags = data;
});
//console.log(`storeTags returned is: ${storeTags}`);
// Transform store string into array of tags to compare
// with hook tags array
//
storeTagsArray = storeTags.split(',');
// compare storeTags to contactTags
// --note both arrays may not be in same order
//
contactTags.forEach(function(contactTag) {
storeTagsArray.forEach(function(storeTag) {
if (storeTag === contactTag) {
tagsEqualCount++;
}
})
})
if (tagsEqualCount === storeTagsArray.length && tagsEqualCount === contactTags.length) {
tagsDidntchange = true;
} else {
setStore(contactEmailAddress, contactTags);
}
// now place contact property variables into output object to pass
//
output = {
'isValentus': isValentus,
'isUpdate': isUpdate,
'isDoubleOptIn': isDoubleOptIn,
'tagsDidntchange': tagsDidntchange,
'contactEmailAddress': contactEmailAddress,
'contactFirstName': contactFirstName,
'contactLastName': contactLastName,
'contactPhoneNumber': contactPhoneNumber,
'contactSource': contactSource,
'contactValentusUSERID': contactValentusUSERID,
'contactStatus': contactStatus,
'contactPhoneCallType': contactPhoneCallType,
'contactInvitedby': contactInvitedby,
'contactInvitedByEmail': contactInvitedByEmail,
'contactInvitedByWebsiteUID': contactInvitedByWebsiteUID,
'contactInvitedByValentusUSERID': contactInvitedByValentusUSERID,
'contactValentusTeam': contactValentusTeam,
'contactTags': contactTags
};
/* for debug */
console.log(output);
/**/
screen shot of error
David here, from the Zapier Platform team.
The root of your issue is on the following line:
storeTagsArray = storeTags.split(',');
If storeTagsArray is undefined, then calling .split() on it crashes.
The reason it's undefined is the way you're handling async code above. Namely, this, directly above:
getStore(contactEmailAddress).then(data => { // line 1
console.log(data); // line 2
storeTags = data; // line 3
});
storeTagsArray = storeTags.split(','); // line 4
You're correct to use .then after the promise, but the code outside the then keeps running in the meantime. The order of execution above is line 1, 4, (eventually) 2, 3. Since 4 runs before storeTagsArray has been initialized, it's still undefined.
The solution here is easy - use await:
storeTags = await getStore(contactEmailAddress)
storeTagsArray = storeTags.split(',');
We wrap all your code in a big async function, so you should be able to await wherever you need it. There's a little more info here.
You've got another .then that you'll need to fix in a similar manner and then your code should run top-to-bottom, just as expected!

How to pass dynamic amount of arguments in function

I try to pass different amount of arguments in different cases.
I have the next code:
function getByteCode(tokenData, incomeData){
incomeData.volume = Number(incomeData.volume) * Math.pow(10,tokenData.decimals);
incomeData.volume = incomeData.volume.noExponents();
let web3 = new Web3();
let instanceContract = new web3.eth.Contract(abi);
instanceContract.options.address = tokenData.address;
let necessaryMethod = instanceContract.methods[incomeData.methodCall];
let methodCall = necessaryMethod(incomeData.destination_address, incomeData.volume);
return methodCall.encodeABI();
} catch (err) {
sails.log(err);
return {
state: 'fail',
message: 'There is error in creation byte code \n' + err
}
}
}
In necessaryMethod I want to pass two arguments in one case and pass three or more argument in other case. How can I do it? Maybe I should use "arguments", but I don`t understand how?
Ok, tank you for the helping. I have used method .apply()
let web3 = new Web3();
let instanceContract = new web3.eth.Contract(abi);
instanceContract.options.address = tokenData.address;
let necessaryMethod = instanceContract.methods[incomeData.methodCall];
let methodCall = necessaryMethod.apply(this, incomeData.argumentsForFunction);
return methodCall.encodeABI();
In first case I called function getByteCode(firstObj, incomeData) and there is next array in incomeData.argumentsForFunction = ['0x323.....', '1500000000'].
In other case I called function getByteCode(firstObj, incomeData) with incomeData.argumentsForFunction = ['0x323.....', '0x3228....', '54454000000']

Javascript - TypeError: listener must be a function

Yet another 'listener must be a function' error.
I double checked all my parameters, checked for correct syntax etc but still can't find where the problem is:
Here are my snippets of code.
in login.js:
global.eventEmitter = require('./helpers/EventEmitter.js');
var packetSwitch = require('./handlers/PacketSwitch.js');
global.ackHandler = require('./handlers/ACKPacketHandler.js');
...
global.eventEmitter.createAndFireEvent('opCodeReceived',packetSwitch.switch(opcode, decrypted, sock));
in PacketSwitch.js:
var packetHandler = require('./PacketHandler.js');
exports.switch = function(opcode, data, sock) {
switch (opcode) {
case 1:
eventEmitter.createAndFireEvent('reqLoginReceived', packetHandler.handleLoginReq(data, sock));
break;
case 2:
eventEmitter.createAndFireEvent('reqDateReceived', packetHandler.handleDateReq(data, sock));
break;
default:
eventEmitter.createAndFireEvent('unknownReceived', packetHandler.handleUnknown(data, sock));
}
};
let's suppose it enters case 2:
in PacketHandler.js:
exports.handleDateReq = function(data, sock) {
global.eventEmitter.createAndFireEvent('handleDateAck', global.ackHandler.handleDateAck(sock));
};
in ACKPacketHandler.js:
exports.handleDateAck = function(sock) {
sock.write("Test!");
};
in EventEmitter.js:
var eventEmitter = require('events');
const myEmitter = new eventEmitter.EventEmitter();
exports.createAndFireEvent = function(event, callback) {
myEmitter.on(event, callback);
myEmitter.emit(event);
};
And here's a screenshot of the error I get:
https://gyazo.com/6047c5917f937aa33f29f9fc40cdf5f7
Your packet handler functions (e.g. handleDateAck()) are not returning functions. In fact, they don't seem to be returning anything. The return value is what you're currently using as the listener function passed to emitter.on().

"ref.child is not a function" when adding .orderByChild.StartAt filter

I have the following code in my controller to go to a firebase database node, loop through the records at that node and return a count of each of the status types into an array (to act as the data for a chartjs chart). The code also waits for changes (edits and deletions) and updates the array accordingly. This all works exactly as I want
var ref = new Firebase("https://my-firebase-url/")
ref.on('child_added', function (snapshot) {
var status = snapshot.val().status.Status;
updateStatusCount(status, addStatus);
ref.child(snapshot.key()).on('child_changed', function (chsnap) {
if (chsnap.key() == 'status') {
var chstatus = chsnap.val().Status;
updateStatusCount(status, removeStatus);
updateStatusCount(chstatus, addStatus);
status = chstatus;
}
});
ref.child(snapshot.key()).on('child_removed', function (rmsnap) {
if (rmsnap.key() == 'status') {
updateStatusCount(status, removeStatus);
}
});
});
function addStatus(index) {
$scope.data[0][index] = $scope.data[0][index] + 1;
}
function removeStatus(index) {
$scope.data[0][index] = $scope.data[0][index] - 1;
}
function updateStatusCount(status, cb) {
switch (status) {
case 'Status 1':
cb(0);
// $scope.data[0][0] = $scope.data[0][0] + 1
break;
case 'Status 2':
cb(1);
// $scope.data[0][1] = $scope.data[0][1] + 1
break;
case 'Status 3':
cb(2);
// $scope.data[0][2] = $scope.data[0][2] + 1
break;
case 'Status 4':
cb(3);
// $scope.data[0][3] = $scope.data[0][3] + 1
break;
case 'Status 5':
cb(4);
// $scope.data[0][4] = $scope.data[0][4] + 1
break;
default:
break;
}
}
});
If I amend my firebase reference to include .orderByChild and .startAt to filter the returned data
var ref = new Firebase("https://my-firebase-url/")
.orderByChild("location").startAt(London)
I get the following warning in the console
FIREBASE WARNING: Exception was thrown by user callback. TypeError: ref.child is not a function
and the changes (edits and deletions) no longer update, I have to do manual page refresh for the correct figures to be displayed. I am really struggling to work out why this is happening when adding the filter.
The Firebase Query class doesn't have a child() method, because... what's the child of a query?
One way to solve the syntax error, split the ref and the query into two variables:
var ref = new Firebase("https://my-firebase-url/");
var query = ref.orderByChild("location").startAt(London);
query.on('child_added', function (snapshot) {
...

Categories