Time promise requests to an API using setInterval or setTimeout - api

I have this issue - I'm trying to fetch a data from a constant url that accepts an integer ID.
I have these integers stacked in array.
I do not want to flood the server with requests so I tried using setInterval and setTimeout to time the requests.
I did take in consideration that a promise might take some time to complete but couldn't figure out how to explicitly apply that.
The results of this code are just:
"[] 1"
const axios = require('axios')
const dataFile = require('../data/car_data')
const modelNameUrl = 'https://www.gov.il/api/mot/carlistprice/api/modelName?yazran_id='
const carId = dataFile.map(data => data.manufacturer_id)
const fetch = async (id) => {
const dataFetched = await axios.get(`${modelNameUrl}${id}`).then()
return dataFetched.data.dgamim_yazran
}
let index = 0
setInterval(async () => {
const data = await fetch(index)
index++
console.log(data, index)
}, 10000)
Additional code for further debugging:
const axios = require('axios')
// const dataFile = require('../data/car_data')
// dataFile.map(data => data.manufacturer_id)
const modelNameUrl = 'https://www.gov.il/api/mot/carlistprice/api/modelName?yazran_id='
let dataArray = []
const fetch = async (id) => {
const dataFetched = await axios.get(`${modelNameUrl}${id}`)
return dataFetched.data.dgamim_yazran
}
function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
let integerSource = [
6, 67, 4, 5, 9, 60, 7, 30, 107, 113, 19,
120, 15, 17, 12, 59, 3, 129, 56, 1, 124, 29,
26, 64, 33, 63, 131, 112, 2, 39, 133, 38, 40,
48, 52, 53, 54, 50, 13, 110, 51, 57, 68, 23,
44, 22, 41, 21, 10, 32, 47, 45, 11
]
async function runLoop() {
for (let index of integerSource) {
try {
const data = await fetch(index);
console.log(data, index);
await delay(5000);
} catch (e) {
console.log(`Error on index ${index}`, e);
throw new Error
}
}
}
runLoop().then(() => {
console.log("all done");
}).catch(err => {
console.log("ended with error\n", err);
});

I'd suggest just using a for loop with await and then a promise-returning delay. This will space out your API calls from when they finish, not from when they started. Your existing scheme does not increment the index right away so it could even make duplicate calls to fetch().
You say you have the desired integers stack in an array, but don't show that in your code. You can either use a for loop that just increments an index or you can use the for loop to pull integers from your array.
function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
let integerSource = [...]; // your array of integer values
async function runLoop() {
for (let index of integerSource) {
try {
const data = await fetch(index);
conole.log(data, index);
await delay(10000);
} catch(e) {
conole.log(`Error on index ${index}`, e);
// decide here whether you continue with further requests
// or throw e to stop further processing
}
}
}
// run the loop here
runLoop().then(() => {
console.log("all done");
}).catch(err => {
console.log("ended with error");
});

Related

html canvas - multiple svg images which all have different fillStyle colors

For a digital artwork I'm generating a canvas element in Vue which draws from an array of multiple images.
The images can be split in two categories:
SVG (comes with a fill-color)
PNG (just needs to be drawn as a regular image)
I came up with this:
const depict = (options) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const myOptions = Object.assign({}, options);
if (myOptions.ext == "svg") {
return loadImage(myOptions.uri).then((img) => {
ctx.drawImage(img, 0, 0, 100, 100);
ctx.globalCompositeOperation = "source-in";
ctx.fillStyle = myOptions.clr;
ctx.fillRect(0, 0, 100, 100);
ctx.globalCompositeOperation = "source-over";
});
} else {
return loadImage(myOptions.uri).then((img) => {
ctx.fillStyle = myOptions.clr;
ctx.drawImage(img, 0, 0, 100, 100);
});
}
};
this.inputs.forEach(depict);
for context:
myOptions.clr = the color
myOptions.uri = the url of the image
myOptions.ext = the extension of the image
While all images are drawn correctly I can't figure out why the last fillStyle overlays the whole image. I just want all the svg's to have the fillStyle which is attached to them.
I tried multiple globalCompositeOperation in different orders. I also tried drawing the svg between ctx.save and ctx.restore. No succes… I might be missing some logic here.
So! I figured it out myself in the meantime :)
I created an async loop with a promise. Inside this I created a temporary canvas per image which I then drew to one canvas. I took inspiration from this solution: https://stackoverflow.com/a/6687218/15289586
Here is the final code:
// create the parent canvas
let parentCanv = document.createElement("canvas");
const getContext = () => parentCanv.getContext("2d");
const parentCtx = getContext();
parentCanv.classList.add("grid");
// det the wrapper from the DOM
let wrapper = document.getElementById("wrapper");
// this function loops through the array
async function drawShapes(files) {
for (const file of files) {
await depict(file);
}
// if looped > append parent canvas to to wrapper
wrapper.appendChild(parentCanv);
}
// async image loading worked best
const loadImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`load ${url} fail`));
img.src = url;
});
};
// depict the file
const depict = (options) => {
// make a promise
return new Promise((accept, reject) => {
const myOptions = Object.assign({}, options);
var childCanv = document.createElement("canvas");
const getContext = () => childCanv.getContext("2d");
const childCtx = getContext();
if (myOptions.ext == "svg") {
loadImage(myOptions.uri).then((img) => {
childCtx.drawImage(img, 0, 0, 100, parentCanv.height);
childCtx.globalCompositeOperation = "source-in";
childCtx.fillStyle = myOptions.clr;
childCtx.fillRect(0, 0, parentCanv.width, parentCanv.height);
parentCtx.drawImage(childCanv, 0, 0);
accept();
});
} else {
loadImage(myOptions.uri).then((img) => {
// ctx.fillStyle = myOptions.clr;
childCtx.drawImage(img, 0, 0, 100, parentCanv.height);
parentCtx.drawImage(childCanv, 0, 0);
accept();
});
}
});
};
drawShapes(this.inputs);

Complex SQL query inside lambda using node js

I am trying to use an npm package called mysql to connect to a db and request data using several joined tables. This query is working on Looker. I am trying to use the same query inside a nodejs lambda function. When I make a simpler query, I don't get any errors. The query works in looker. I am not sure how to properly format it so that the query works here. I keep getting syntax error responses no matter how I try formatting it.
This is my lambda function
`
const aws = require('aws-sdk');
const mysql = require('mysql');
const NAMES = ['mp-admin-db-host','mp-admin-db-user','mp-admin-db-password','mp-admin-db-name'];
const MYSQL_CONNECTION_KEYS = [ 'host', 'user', 'password', 'database']
exports.handler = async (event) => {
console.log("STARTED");
const ssm = new aws.SSM({region: 'us-east-1'});
const { Parameters } = await ssm.getParameters({
Names: NAMES,
WithDecryption: true
}).promise();
const config = {};
MYSQL_CONNECTION_KEYS.forEach((key, i)=> {
const param = Parameters.find(({Name}) => Name === NAMES[i])
config[key] = param.Value
})
const con = mysql.createConnection(config)
con.connect(function(err) {
if (err) throw err;
console.log('CONNECTED');
con.query(SQL_QUERY, function (err, result, fields) {
if (err) throw err;
console.log('RESPONSED');
});
});
return {
status: 200,
body: config
};
};
`
This is my sql query
`
'SELECT
`license_plate`.`license_plate_number` AS `license_plate.license_plate_number`,
`lotted_product`.`lot_code` AS `lotted_product.lot_code`,
`grade`.`name` AS `grade.name`,
`lotted_product`.`title` AS `lotted_product.title`,
`lotted_product`.`brand` AS `lotted_product.brand`,
`lotted_product`.`quantity` AS `lotted_product.quantity`,
`lotted_product`.`msrp` AS `lotted_product.msrp`,
`lotted_product`.`item_description` AS `lotted_product.item_description`,
`lotted_product`.`upc` AS `lotted_product.upc`,
`lotted_product`.`identifier_value` AS `lotted_product.identifier_value`,
`lotted_product`.`color` AS `lotted_product.color`,
`lotted_product`.`mpn` AS `lotted_product.mpn`,
`lotted_product`.`item_weight` AS `lotted_product.item_weight`,
`lotted_product`.`unit_description` AS `lotted_product.unit_description`,
`lotted_product`.`size` AS `lotted_product.size`,
`lotted_product`.`damage_description` AS `lotted_product.damage_description`,
`lotted_product`.`item_length` AS `lotted_product.item_length`,
`lotted_product`.`item_width` AS `lotted_product.item_width`,
`lotted_product`.`item_depth` AS `lotted_product.item_depth`,
`lotted_product`.`specification` AS `lotted_product.specification`,
`lotted_product_picture`.`pic_url` AS `lotted_product_picture.pic_url`
FROM
`bidfta`.`lotted_product` AS `lotted_product`
LEFT JOIN `bidfta`.`lotted_product_picture` AS `lotted_product_picture` ON `lotted_product`.`id` = `lotted_product_picture`.`lotted_product_id`
LEFT JOIN `bidfta`.`grade` AS `grade` ON `lotted_product`.`grade_id` = `grade`.`id`
LEFT JOIN `bidfta`.`license_plate_product` AS `license_plate_product` ON `lotted_product`.`id` = `license_plate_product`.`lotted_product_id`
LEFT JOIN `bidfta`.`license_plate` AS `license_plate` ON `license_plate_product`.`license_plate_id` = `license_plate`.`id`
WHERE `license_plate`.`license_plate_number` = 'MP110122'
GROUP BY
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21
ORDER BY
`license_plate`.`license_plate_number`
LIMIT 500'
`
I try different variations of deleting spaces and using ', ", `.

For loop inside a Redis queue does not work as expected in NestJs

I have the following code, basically it is doing a bruteforce on a key of a hash in the first 4 bytes. Then I loop through each of these positions to test all possible combinations. If I put this code inside the service it runs normally and takes about 200 seconds to find all possible combinations of the first 4 bytes.
But when you're doing long operations, it's good to have a queue to do this in the background. That's what I did, I added it to a nestjs queue with redis but inside the queue when I use for it seems that they are shuffled and they all end together in less than 5 seconds, besides that I don't find the correct combination. And if I use a forEach it either doesn't work or the program crashes during execution.
Basically the first 4 bytes are [192, 156, 127, 0, ...] but it doesn't find it when it's inside a queue. How can I make the background queue run normally as if it were in the service?
import * as crypto from 'crypto';
const DIFFICULTY = {
legendary: {
maxValues: [255, 255, 255, 1],
},
hard: {
maxValues: [255, 255, 255, 0],
},
medium: {
maxValues: [255, 255, 127, 0],
},
easy: {
maxValues: [255, 255, 64, 0],
},
};
#Processor('decrypt-queue')
export class DecryptConsumer {
constructor(
#InjectRepository(Chest) private readonly repository: Repository<Chest>,
) {}
#Process('decrypt-job')
async decryptJob(job: Job) {
const code = job.data;
await job.progress(50);
const chest = await this.repository.findOne({
where: {
code: code,
},
});
await this.repository.save({
...chest,
status: ChestStatus.Oppening,
});
const iv = Buffer.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const original = chest.key;
const range = ({
from = 0,
to,
step = 1,
length = Math.ceil((to - from) / step),
}): number[] => Array.from({ length }, (_, i) => from + i * step);
const first = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[0],
step: 1,
});
const second = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[1],
step: 1,
});
const third = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[2],
step: 1,
});
let four = range({
from: 0,
to: DIFFICULTY[chest.difficulty].maxValues[3],
step: 1,
});
four = [0];
// first.forEach(async (i) => {
// second.forEach(async (j) => {
// third.forEach(async (k) => {
// four.forEach(async (l) => {
// console.log(i, j, k, l);
// if (
// i === original[0] &&
// j === original[1] &&
// k === original[2] &&
// l === original[3]
// ) {
// console.log(i, j, k, l, end());
// const decipher = await crypto.createDecipheriv(
// 'aes-128-cbc',
// Buffer.from([i, j, k, l, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
// iv,
// );
// let decrypted = await decipher.update(code, 'hex', 'utf8');
// decrypted += decipher.final('utf8');
// if (decrypted.includes('Hello')) {
// await this.repository.save({
// ...chest,
// status: ChestStatus.Openned,
// });
// await job.progress(100);
// // return {
// // decrypted,
// // };
// } else {
// }
// }
// });
// });
// });
// });
for (let i = 0; i < DIFFICULTY[chest.difficulty].maxValues[0]; i++) {
for (let j = 0; j < DIFFICULTY[chest.difficulty].maxValues[1]; j++) {
for (let k = 0; k < DIFFICULTY[chest.difficulty].maxValues[2]; k++) {
for (let l = 0; l < DIFFICULTY[chest.difficulty].maxValues[3]; l++) {
if (
i === original[0] &&
j === original[1] &&
k === original[2] &&
l === original[3]
) {
console.log(i, j, k, l, end());
const decipher = await crypto.createDecipheriv(
'aes-128-cbc',
Buffer.from([i, j, k, l, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
iv,
);
let decrypted = await decipher.update(code, 'hex', 'utf8');
decrypted += decipher.final('utf8');
if (decrypted.includes('Hello')) {
await this.repository.save({
...chest,
status: ChestStatus.Openned,
});
await job.progress(100);
// return {
// decrypted,
// };
} else {
}
}
}
}
}
}
await this.repository.save({
...chest,
status: ChestStatus.Locked,
});
await job.progress(100);
// return {
// decrypted: false,
// };
}
}

how to create pdf file in react-native?

error : null is not an object evaluating '_PDFLib.default.createPDF'
https://github.com/Hopding/react-native-pdf-lib
I use the pdf library, can you tell me why the error occurs?
If you use await(const docsDir = await PDFLib.getDocumentsDirectory();), you get an error message like this: error - Can not use keyword 'await' outside an async function.
If you know how to create a pdf file, please let me know.
pdfButton = () => {
const page1 = PDFPage
.create()
.setMediaBox(200, 200)
.drawText('You can add text and rectangles to the PDF!' , {
x: 5,
y: 235,
color : '#007386',
})
.drawRectangle({
x: 25,
y: 25,
width: 150,
height: 150,
color: '#FF99CC',
})
.drawRectangle({
x: 75,
y: 75,
width: 50,
height: 50,
color: '#99FFCC',
});
//It's like a problem.
// const docsDir = await PDFLib.getDocumentsDirectory();
const pdfPath = './data/ex.pdf'; //path to create pdf folder
PDFDocument
.create(pdfPath)
.addPages(page1)
.write() // Returns a promise that resolves with the PDF's path
.then(path => {
console.log('PDF created at: ' + path);
// Do stuff with your shiny new PDF!
});
The pdfButton function must be an async function
pdfButton = async () => {
...
const docsDir = await PDFLib.getDocumentsDirectory();
const pdfPath = `${docsDir}/ex.pdf`;
}

Async/Await function returning _40: 0, _65: 0, _55: null, _72: null

I got this { _40: 0, _65: 0, _55: null, _72: null } returned from Async/Await function when trying to get the original size of an image. Refer https://www.npmjs.com/package/react-native-image-size for the function usage.
Here is my code.
getImgSize = async (url) => {
const {width, height} = await ImageSize.getSize(url);
const imgSize = { width: width, height: height }
console.log(imgSize) // result is { width: 950, height: 634 }
return imgSize;
}
function getImage(){
var imgSize = getImgSize("https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzEwNC84MzAvb3JpZ2luYWwvc2h1dHRlcnN0b2NrXzExMTA1NzIxNTkuanBn");
console.log(imgSize) // result after returned { _40: 0, _65: 0, _55: null, _72: null }
}
I expected the result to be something like { width: 950, height: 634 } but the result I mentioned been returned instead.
You are calling an async function which means it's a promise. You gotta wait for the result.
So either use await
getImage = async () => {
var imgSize = await getImgSize("https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzEwNC84MzAvb3JpZ2luYWwvc2h1dHRlcnN0b2NrXzExMTA1NzIxNTkuanBn");
console.log(imgSize);
}
or handle it this way
getImage = () => {
getImgSize('https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzEwNC84MzAvb3JpZ2luYWwvc2h1dHRlcnN0b2NrXzExMTA1NzIxNTkuanBn').then((imgSize) => {
console.log(imgSize);
});
}
You need to add await and async function:
getImgSize = async (url) => {
const {width, height} = await ImageSize.getSize(url);
const imgSize = { width: width, height: height }
console.log(imgSize) // result is { width: 950, height: 634 }
return imgSize;
}
async function getImage(){
var imgSize = await getImgSize("https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzEwNC84MzAvb3JpZ2luYWwvc2h1dHRlcnN0b2NrXzExMTA1NzIxNTkuanBn");
console.log(imgSize) // result after returned { _40: 0, _65: 0, _55: null, _72: null }
}
You must use async with await or use the then() => against it lets look at that and use it where you need to wait .
Try it
getImgSize("<Image URL>")
.then((imgSize)=>console.log(imgSize))
or put it in async/await
getImage = async () => {
var imgSize = await getImgSize("<Image URL>");
console.log(imgSize);
}