Getting SyntaxError with async/await - javascript

I have the following the following code I am trying to run with node.js:
ethereum-block-by-date.js
module.exports = class {
constructor(web3) {
this.web3 = web3.constructor.name === 'Web3' ? web3 : { eth: web3 };
this.checkedBlocks = {};
this.savedBlocks = {};
this.requests = 0;
}
.
.
.
async getEvery(duration, start, end, every = 1, after = true) {
start = moment(start), end = moment(end);
let current = start, dates = [];
while (current.isSameOrBefore(end)) {
dates.push(current.format());
current.add(every, duration);
}
if (typeof this.firstBlock == 'undefined' || typeof this.latestBlock == 'undefined' || typeof this.blockTime == 'undefined') await this.getBoundaries();
return await Promise.all(dates.map((date) => this.getDate(date, after)));
}
.
.
.
And
getBlockNumber.js
const EthDater = require('ethereum-block-by-date');
const { ethers } = require('ethers');
const url = "node url";
const provider = new ethers.providers.WebSocketProvider(url);
const dater = new EthDater(
provider
);
let blocks = await dater.getEvery('hours', '2018-11-15T00:00:00Z', '2018-11-22T00:00:00Z');
console.log(blocks);
When I run node getBlockNumber.js, I get the SyntaxError: await is only valid in async function referring to the let blocks = await dater.getEvery() function call.
If getEvery() is defined as aync in ethereum-block-by-date.js, then why is it returning this SyntaxError? When I remove await from dater.getEvery() it returns a Promise object.

The issue is resolved when I put the await dater.getEvery() inside an async function and then call the function:
async function getBlocks() {
let blocks = await dater.getEvery('hours', '2018-11-15T00:00:00Z', '2018-11-22T00:00:00Z');
console.log(blocks);
}
getBlocks();

Related

how to use trim in fetch url

how to retrieve the verif code, here I try to do the next regex using trim but an error message appears "TypeError: Cannot read properties of undefined (reading 'trim')"
and I just want to fetch the verification code, like in the image
my code
const checkInboxUrl = 'https://getnada.com/api/v1/inboxes/';
const getMessageUrl = 'https://getnada.com/api/v1/messages/html/';
const refreshMailboxUrl = 'https://getnada.com/api/v1/u/';
/* eslint-disable no-unused-vars */
class Getnada {
constructor() {
this.email = '';
this.verificationCode = '';
}
async getEmail(email = 'urmxhbwrz#getnada.com') {
this.email = email;
return this;
}
async getMailbox(pattern, sleepTime = 5000) {
await sleep(sleepTime);
const timestamp = Math.floor(new Date().getTime() / 1000);
const refreshMailboxResponse = await fetch(refreshMailboxUrl + this.email + '/' + timestamp);
const checkInboxResponse = await fetch(checkInboxUrl + this.email);
const checkInboxJson = await checkInboxResponse.json();
const getMessageResponse = await fetch(getMessageUrl + checkInboxJson.msgs[0].uid);
const readInbox = await getMessageResponse.text();
const regex = new RegExp(pattern);
const verificationCodeMatch = regex.exec(readInbox);
this.verificationCode = verificationCodeMatch[1].trim();
console.log(verificationCodeMatch)
return this;
}
}
const getnada = new Getnada();
async function main() {
console.log((await getnada.getEmail()))
console.log((await getnada.getMailbox()))
}
main();
https://getnada.com/api/v1/messages/html/8lra5CwOQcHvja3mpQZgO7G5RPTS3W
To retrieve the verification code, you can try to change this lines :
const regex = new RegExp(pattern);
const verificationCodeMatch = regex.exec(readInbox);
this.verificationCode = verificationCodeMatch[1].trim();
to :
const verificationCodeMatch = pattern.exec(readInbox);
this.verificationCode = verificationCodeMatch[0].trim();
And change this line too :
console.log((await getnada.getMailbox()))
to :
console.log((await getnada.getMailbox(/\b\d{6,6}\b/)));
This regex /\b\d{6,6}\b/ will filter out strings containing exactly 6 digits of numbers which is the verification code.

TypeError: this is not a function

I have the following 2 files root/functions/util/constants.js and root/functions/handlers/images.js. The following are their source code
images.js
const path = require("path");
const os = require("os");
const sharp = require('sharp');
const fs = require('fs-extra');
const { uuid } = require("uuidv4");
const { Storage } = require('#google-cloud/storage');
const config = require("../util/config");
const gcs = new Storage({
projectId: config.projectId
});
const bucket = gcs.bucket(config.storageBucket);
const {
INVALID_TYPE_MESSAGE,
POST_SMALL_IMAGE_TYPE,
POST_MEDIUM_IMAGE_TYPE,
select_size_from_type
} = require("../util/constants");
const {
USER_PUBLIC_PROFILE_IMAGE
} = require("../util/schema")
const {error_response} = require("../util/validators");
exports.async_resize = async function(url, type) {
const size = select_size_from_type(type);//code beyond this are not executed
//some other code...
constants.js
const {error_response} = require("./validators");
const { admin } = require("./admin")
//Entity and collection names
//also contains fields of maps of schemas
const {
USER_PUBLIC_PROFILE_IMAGE
} = require("./schema");
const LIKES_COLLECTION = "likes";
const COMMENTS_COLLECTION = "comments";
const POSTS_COLLECTION = "posts";
const NOTIFICATIONS_COLLECTION = "notifications";
const FOLLOWERS = "followers";
const FOLLOWING = "following";
const PUBLIC_FOLLOWERS_SUBCOLLECTION = FOLLOWERS;
const PUBLIC_FOLLOWING_SUBCOLLECTION = FOLLOWING;
const USERS_PUBLIC_COLLECTION = "users_public";
const USERS_PRIVATE_COLLECTION = "users_private";
const PRIVATE_FOLLOWERS_SUBCOLLECTION = FOLLOWERS;
const PRIVATE_FOLLOWING_SUBCOLLECTION = FOLLOWING;
const LIKE_TYPE = "like";
const COMMENT_TYPE = "comment";
const POST_TYPE = "post";
const NOTIFICATION_TYPE = "notification"
const POST_SMALL_IMAGE_TYPE = "small";
const POST_MEDIUM_IMAGE_TYPE = "medium";
const POST_MAXIMUM_ORIGINAL_TYPE = "original";
const SERVER_TIME = admin.firestore.FieldValue.serverTimestamp();
const INVALID_TYPE_MESSAGE = "Invalid recipient type";
const select_collection_from_type = (type) => {
if (type === LIKE_TYPE) {
return LIKES_COLLECTION;
} else if (type === POST_TYPE) {
return POSTS_COLLECTION;
} else if (type === COMMENT_TYPE) {
return COMMENTS_COLLECTION;
} else {
return error_response("Data type is not within scope of project");
}
}
//can be used for profile_image also
const select_size_from_type = function (type) {
if (type === POST_SMALL_IMAGE_TYPE) {
return 64;
} else if (type === POST_MEDIUM_IMAGE_TYPE) {
return 128;
} else if (type === POST_MAXIMUM_ORIGINAL_TYPE) {
return 256;
} else if (type === USER_PUBLIC_PROFILE_IMAGE) {
return 1; //same as before, need a better number for this
//
} else {
return error_response("Data type is not within scope of project");
}
}
module.exports = {
LIKE_TYPE,
LIKES_COLLECTION,
COMMENT_TYPE,
COMMENTS_COLLECTION,
PUBLIC_FOLLOWERS_SUBCOLLECTION,
PUBLIC_FOLLOWING_SUBCOLLECTION,
PRIVATE_FOLLOWERS_SUBCOLLECTION,
PRIVATE_FOLLOWING_SUBCOLLECTION,
USERS_PUBLIC_COLLECTION,
USERS_PRIVATE_COLLECTION,
POST_TYPE,
POSTS_COLLECTION,
INVALID_TYPE_MESSAGE,
SERVER_TIME,
NOTIFICATIONS_COLLECTION,
POST_SMALL_IMAGE_TYPE,
POST_MEDIUM_IMAGE_TYPE,
POST_MAXIMUM_ORIGINAL_TYPE,
select_collection_from_type,
select_size_from_type
};
I tried running a script and it keeps telling me that
TypeError: select_size_from_type is not a function
at exports.async_resize (/Users/Isaac/root/functions/handlers/images.js:36:16)
but I really dont see any syntax error. I'm using Webstorm and the functions can be navigated. Can someone enlighten me what else can be the cause of the syntax error?
Update
I also tried console.log(select_size_from_type); in images.js, console.log(select_size_from_type); before it was exported in constants.js. It prints undefined and [Function: select_size_from_type] respectively. Even when I tried changing the signature of async_resize as well as select_size_from_type, all of them gave the same error as well. Any other function which does not involve select_size_from_type works perfectly.
Functions can be defined in two ways
Way 1
function my_function_name (arguments) {
...function body
}
Way 2
const my_function_name = function (arguments) {
... function body
}
In your case, it seems like you are trying to mix both the ways.
Try changing your function definition to
exports.async_resize = async(url, type) => {
...function body
}
try this
const size = this.select_size_from_type(type);//code beyond this are not executed
or export your file like this
module.exports.select_size_from_type=select_size_from_type
or
module.exports={size_type : select_size_from_type}
and then require it like this
const getsizefromtype=require(....)
select_size_from_type= getsizefromtype.size_type

Node Js - SyntaxError: await is only valid in async function

I have below code in service.js file.
exports.getSeminarDetailsById = async function (seminarId) {
try {
let SeminarList = [];
var seminarData = await SeminarRepository.getSeminarDetailsById(seminarId);
if (seminarData && seminarData.length > 0) {
let userIdList = [...new Set(seminarData.map(x => x.user_id))];
if (userIdList && userIdList.length > 0) {
let userDetails = await EmployeeRepository.getEmployeeDetailsByUserIds(userIdList);
if (userDetails && userDetails.length > 0) {
seminarData.forEach(element => {
let seminarDetail;
let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
let categoryName;
if (element.category_id == 1)
categoryName = AppConstants.seminarCategoryName.TECHNICAL;
else
categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
await mapAttachmentWithSeminar(seminarId, seminarDetail);
console.log("second", seminarDetail);
SeminarList.push(seminarDetail);
});
}
}
}
return SeminarList;
} catch (err) {
console.log(err);
throw err;
}
}
Here error comes on await mapAttachmentWithSeminar(seminarId, seminarDetail); and it is defined in the same file as below.
async function mapAttachmentWithSeminar(seminarId, seminarDetail) {
var seminarAttachmentDetails = await SeminarRepository.getSeminarAttachmentDetailsById(seminarId);
if (seminarAttachmentDetails && seminarAttachmentDetails.length > 0) {
let AttachmentDetails = [];
seminarAttachmentDetails.forEach(element => {
let attachmentDetails = new SeminarAttachmentDetails(element);
AttachmentDetails.push(attachmentDetails);
});
seminarDetail.SeminarAttachmentDetails = AttachmentDetails;
}
else {
seminarDetail.SeminarAttachmentDetails = null;
console.log("first", seminarDetail);
}
}
If I remove the await function, then console.log("second", seminarDetail); will be executed first before executing the function mapAttachmentWithSeminar(). So that the value of SeminarAttachmentDetails returning from that function will be missed as shown below:
This was the expected output.
Instead of using .forEach you could go with a classic for loop
for(let i = 0; i < seminarData.length; i++){
let element = seminarData[i];
let seminarDetail;
let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
let categoryName;
if (element.category_id == 1)
categoryName = AppConstants.seminarCategoryName.TECHNICAL;
else
categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
await mapAttachmentWithSeminar(seminarId, seminarDetail);
console.log("second", seminarDetail);
SeminarList.push(seminarDetail);
}
First you are using wrong async await. You are awaiting inside the scope of a function which is not async.
Here:
seminarData.forEach(element => {
let seminarDetail;
let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
let categoryName;
if (element.category_id == 1)
categoryName = AppConstants.seminarCategoryName.TECHNICAL;
else
categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
await mapAttachmentWithSeminar(seminarId, seminarDetail);
console.log("second", seminarDetail);
SeminarList.push(seminarDetail);
});
You should have this
// here you have the SeminarList but promisified
// with the form Promise<SeminarListItem>[]
// to get the values out of the promises you have to await this array
const promisifiedSeminarList = seminarData.map((element)=>{
let userName = userDetails.filter(x => x.user_id == element.user_id).map(
x => x.userfullname)[0]
);
const categoryName = elemenet.category_id == 1
? AppConstants.seminarCategoryName.TECHNICAL
: AppConstants.seminarCategoryName.NONTTECHNICAL;
const seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
return mapAttachmentWithSeminar(seminarId, seminarDetail);
});
// now
const seminarList = await Promise.all(promisifiedSeminarList);
For that to work you need that the function mapAttachmentWithSemniar returns a value which is not happening
every nested function should be declared as async as well as parent's.
in your case this declaration is missed in one of nesting level, pay attention on this part of code
seminarData.forEach(async element => {
// ^^^^ async missed here
let seminarDetail;
let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
let categoryName;
if (element.category_id == 1)
categoryName = AppConstants.seminarCategoryName.TECHNICAL;
else
categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
await mapAttachmentWithSeminar(seminarId, seminarDetail);
console.log("second", seminarDetail);
SeminarList.push(seminarDetail);
});

using promises and async for protobufjs loadcall

I am trying to figure out the best way to re-write the following code:
var api = function(id, contract) {
var callback = function (error, root) {
if (error)
throw error;
var by = Buffer.from(contract,'base64')
var es = root.lookupType("Contract")
var esMsg = es.decode(by)
var esBytes = es.encode(esMsg).finish()
signature = id.sign(esBytes).toString('base64')
}
return new Promise((resolve, reject) => {
protobuf.load("contract.proto", callback)
})
}
var signContract = async(privateKey, contract) => {
let signature
var id = await crypto.keys.unmarshalPrivateKey(Buffer.from(privateKey, 'base64'))
result = await api(id,contract,signature)
}
function getSessionSignature (hash, time) {
return config.id + ":" + hash + ":" + time
}
module.exports = configure(({ ky }) => {
return async function * signbatch (input, options) {
var contracts = input.Contracts
for (var i = 0 ; i < contracts.length ; i++) {
contracts[i].contract = await signContract(config.PrivKey, contracts[i].contract)
}
//add signed contracts to the searchParams
searchParams.append("arg", JSON.stringify(contracts))
let res
res = await ky.post('storage/upload/signbatch', {
searchParams
}).json()
yield JSON.stringify({})
} else {
yield JSON.stringify({error:"Private key not found"})
}
}
})
My issue is how do I write the sign async code to pass in privateKey and contract variables to api var function and return the signature back to the result variable to be assigned to contracts[i].contract ? Please note that the id.sign(..) function is Promise inside the callback function.
You need to resolve the promise in the api function, the docs suggest you could use the single argument variant here, e.g.
var root = await protobuf.load("contract.proto");
... // (The code you currently by have in 'callback'
return signature;
As the generator is async, yield will emit a Promise which you can (obviously) handle with either .then or await

Pagination in Zapier

I am trying following code to get all records from a paginated API in Zapier.
const limitPerPage = 20;
const apiUrl = "https://myurl.com/data";
var lastCursor = null;
var output = null;
const getContent = async function (cursor) {
let actualUrl = apiUrl + `?cursor=${cursor}&limit=${limitPerPage}`;
var apiResults = await fetch(actualUrl)
.then(resp => {
return resp.json;
});
}
const getEntireContentList = async function (cursor) {
const results = await getContent(cursor);
console.log("Retreiving data from API for cursor : " + cursor);
if (results.metadata.cursor !== "") {
return results.concat(await getEntireContentList(results.metadata.cursor));
} else {
return results;
}
};
(async() => {
const entireList = await getEntireContentList();
console.log(entireList);
output = entireList;
callback(null, entireList);
})();
I get error as
You did not define output! Try output = {id: 1, hello: await Promise.resolve("world")};
How can I fix this?
Your problem is that though you're awaiting in that function, the top-level carries on and execution ends before your code has had a chance to run.
The good news is, Zapier wraps your code in an async function already, so you can use await at the top level (per these docs).
Try this instead:
const limitPerPage = 20;
const apiUrl = "https://myurl.com/data";
let lastCursor = null;
// var output = null; // zapier does this for you already
const getContent = async function (cursor) {
const actualUrl = apiUrl + `?cursor=${cursor}&limit=${limitPerPage}`;
const rawResponse = await fetch(actualUrl)
return resp.json() // async function, you had it as a property
}
const getEntireContentList = async function (cursor) {
const results = await getContent(cursor);
console.log("Retreiving data from API for cursor : " + cursor);
if (results.metadata.cursor !== "") {
return results.concat(await getEntireUserList(results.metadata.cursor)); // should this be named getEntireContentList?
} else {
return results;
}
};
return {
results: await getEntireContentList()
}
I noticed this is a recursive approach. That's fine, but remember that you've got limited execution time. You also might hit memory limits (depending on how many objects you're returning), so keep an eye on that.

Categories

Resources