Use promise to delay mocha - javascript

I'm using mocha and zombie.
My goal is to load data from website <a> tags from website then query name and href. So far this is working:
const Browser = require('zombie')
const browser = new Browser()
browser.visit('page', () => {
let temp = browser.document.querySelectorAll('a selector')
for (let i = 0; i < temp.length; i++) {
browsers.push({ name: temp[i].innerHTML, url: temp[i].href })
}
delete temp
})
My next step would be using this data in testing.
const data = [{ name: 'name', url: 'test' }]
describe('test with for', () => {
for (let i = 0; i < data.length; i++) {
it(data[i].name, () => {
// test code with url of data[i]
})
}
})
The only problem I have is that data array is filled asynchronously and it has to be present at time of invoking it function.
I tryed using before but i saw that it does not make sence here (because of invoking async function don't stop code to execute and only function pased in it can depend on async data)
So I tryed to do this using Promise but it also failed.
const data = []
new Promise((resolve, reject) => {
// filing data
resolve()
}).then(() => {
describe('...', () => {
for (let i = 0; i < data.length; i++) {
it (data[i].name, () => {})
}
})
})
I looked at mocha documentation and didn't find solution :/
How should I solve this problem?

Ok i found solution, problem was my mistake i forgot to remove describe inwith my browser reading was contained that's why --delay did not work.
Running code:
const { describe, it } = require('mocha')
const { assert, expect } = chai = require('chai')
const Browser = require('zombie')
const browser = new Browser()
const browsers = []
new Promise((resolve, reject) => {
browser.visit('site', () => {
let temp = browser.document.querySelectorAll('selector')
for (let i = 0; i < temp.length; i++) {
browsers.push({ name: temp[i].innerHTML, url: temp[i].href })
}
delete temp
resolve()
})
}).then(() => {
describe('Get browser name', () => {
for (let i = 0; i < browsers.length; i++) {
it(browsers[i].name, () => {
})
}
})
run()
})

Related

How do I assign an array to another array?

Here is my code
export default class Application extends EventEmitter {
constructor() {
super();
this.config = config;
this.data = {
planets: [planetData]
};
this.init();
let url;
let count;
let planetData = []
let promises = [];
//turn through the pages
for (let p = 1; p < 7; p++) {
url = `https://swapi.boom.dev/api/planets?page=${p}`;
//fetch data
promises.push(fetch(url).then(res => res.json())
.then(data => {
//push data to array
for (let i = 0; i < data.results.length; i++) {
planetData = planetData.concat(data.results[i]);
}
}));
}
Promise.all(promises)
.then(() => {
console.log(planetData.length, '=>', planetData);
})
}
I need help assigning the planetData array to this.data{}. I tried the following this.data{ planets: [planetData], but it gave an error "Cannot access 'planetData' before initialization", which was expected. My syntax is also probably wrong, but I'm really new to JS.
You should assign the variable after the planetData array has been populated.
Perhaps you can try something like this:
Promise.all(promises)
.then(() => {
console.log(planetData.length, '=>', planetData);
})
.then(() => {
this.data.planets = planetData;
})
You can assign planetData to the key planets later in your code using:
this.data.planets = planetData;

Maintain Order In Async Function Node JS

I am new to NodeJs.
I want to push elements in files array in order of url. But i am getting random order .
Below is the code for same. Can anyone suggest what i am doing wrong here.
const mergePdf =async (urlArray, files) => {
for (let i = 0; i < urlArray.length; i++) {
try {
const pdfBytes = await fetch(urlArray[i]).then((res) => {
return res.arrayBuffer();
});
let bytes = new Uint8Array(pdfBytes);
files[i]=bytes;
} catch (err) {
console.log(err);
}
}
}
write seprate function of your api call in promises like
const other_func = (url) => {
return new Promise(async (resolve) => {//updated line
try {
const pdfBytes = await fetch(url).then((res) => {
let bytes = new Uint8Array(pdfBytes);
resolve(bytes);// return value pass in resolve method [Updated]
});
} catch (err) {
console.log(err);
}
})
}
and in your original function call this function using await
like
const mergePdf =async (urlArray, files) => {
for (let i = 0; i < urlArray.length; i++) {
files[i] = await other_func(urlArray[i])
}}

Node.js for() loop value keep increasing?

I have setup an interval and loop for batch orders,
However the batch number in for loop keeps increasing.
Here is my code
const Web3 = require('web3')
const web3 = new Web3('ws://127.0.0.1:8546')
const accounts = require('./tps.json');
const quoteInterval = 5 * 1000;
const batch = new web3.BatchRequest();
const sendTransactions = async () => {
try {
for (let i = 0; i < 100; i++) {
let account = accounts[i];
const tx = web3.eth.sendTransaction.request(
{
from: web3.utils.toChecksumAddress("0xa00ce1f7fbf8298f4163ab23de8752942bdff98e"),
to: web3.utils.toChecksumAddress(account),
gas: 21000,
gasPrice: 1000000000,
value: 1
}
)
batch.add(tx)
}
await batch.execute().then(console.log);
} catch (error) {
console.log(error);
process.exit(1)
}
};
if (web3.eth.net.isListening()) {
sendTransactions();
setInterval(() => {
sendTransactions();
}, quoteInterval);
}
i value wasn't increasing, however, sendTransactions() function is doing like 2, 3, 4 or 5 times after every interval
Where did you see that the value of i keep increasing? Did you put some console.log somewhere?
The following simplified version (with the same context operations of yours) is working fine:
async function asyncOperation(x) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(x) # this always outputs 0 < x < 5
resolve()
}, 50)
})
}
const asyncFunction = async () => {
allPromises = []
for (let i = 0; i < 5; i++) {
allPromises.push(asyncOperation(i))
}
await Promise.all(allPromises)
};
setInterval(() => asyncFunction(), 500)
const quoteInterval = 5*1000;
const sendTransactions = async () => {
try {
for (let i = 0; i < 100; i++) {
console.log(i);
}
} catch (error) {
console.log(error);
}
};
sendTransactions();
setInterval(() => {
sendTransactions();
}, quoteInterval);
As per the logic, It will not go above the 100

How do I wait until all requests are finished?

How could I make the sortOrder function run once the getOrders function is fully completed?
I thought using a callback, so I expect getOrders to terminate and execute the sortOrder function, but I donĀ“t know how to do that. What should I do, any sugestions?
mounted () {
this.user = this.$q.localStorage.get.item('userInfo')
axios.get(`${api.getOrders}${this.user.cpf}`).then(response => {
this.orders = response.data
if (this.orders !== '') {
this.$q.loading.show()
this.getOrders(callback => {
this.sortOrder()
})
}
})
},
methods: {
getOrders: function () {
for (let i = 0; i < this.orders.length; i++) {
axios.get(api.obterOrderInfo(this.orders[i].orderId)).then(response => {
this.orderInfo = this.orderInfo.concat(response.data)
})
}
},
sortOrder: function () {
this.orderInfo.sort(this.compare)
this.$q.loading.hide()
},
compare: function (x, y) {
return x.creationDate < y.creationDate
}
}
getOrders: function () {
// Create array of requests
const requests = [];
for (let i = 0; i < this.orders.length; i++) {
requests.push(axios.get(api.obterOrderInfo(this.orders[i].orderId)))
}
// Map array of responses to orderInfo
return Promise.all(requests).then(results => this.orderInfo = results.map(result => result.data))
},
You'll need to wrap your promises together and solve them with a Promise.all like this:
getOrders: function () {
let promises = []
for (let i = 0; i < this.orders.length; i++) {
const promise = axios.get(api.obterOrderInfo(this.orders[i].orderId)).then(response => {
this.orderInfo = this.orderInfo.concat(response.data)
})
promises.push(promise)
}
Promise.all(promises)
.then(() => {
this.sortOrder()
})
},

https requests in loop, call function after last request has been made node

Assuming I am calling https a multiple times to retrieve data, and I want to call a function formatJsonToLocale at the end of the last request. Is there a way to determine when that request has ended, other than checking for the last element of the array.
let sheetsArray = []
function sheetsAsJsonById (ids) {
for (let i = 0; i < ids.length; i++) {
const queryUrl = `sheets.html`
https
.get(queryUrl, res => {
let stream = []
res
.on('data', function (data) {
stream.push(data)
})
.on('end', function () {
let data = Buffer.concat(stream)
data = JSON.parse(data)
sheetArrays.push(data['values'])
formatJsonToLocale(sheetsArray) // <----- call this one after last request
})
})
.on('error', err => {
console.error(`Error in response: ${err}`)
})
}
}
when I call formatJsonToLocale outside of the function I will have the problem that the former function might not be finished as https handles stuff asynchronously.
Any suggestions on how to handle this?
You would need to keep track of execution of async code (https.get) that is getting executed within for loop. This can be achieved using promises as below:
let sheetsArray = []
function sheetsAsJsonById (ids) {
let promises = []
for (let i = 0; i < ids.length; i++) {
const queryUrl = `sheets.html`
promises.push(makeHTTPRequest(queryUrl))
}
Promise.all(promises).then((sheetArrays) => {
formatJsonToLocale(sheetsArray)
})
}
const makeHTTPRequest = (url) => {
return new Promise((resolve, reject) => {
https
.get(url, res => {
let stream = []
res
.on('data', function (data) {
stream.push(data)
})
.on('end', function () {
let data = Buffer.concat(stream)
data = JSON.parse(data)
resolve(data)
})
.on('error', err => {
console.error(`Error in response: ${err}`)
})
})
}
If you want to stick to callbacks you could use async.each function of async node module.
Wrap https.get in a Promise, which resolves on the end event, and rejects on any error. Now you can await the promise, and call the function once the for loop is done
let sheetsArray = []
function sheetsAsJsonById(ids) {
for (let i = 0; i < ids.length; i++) {
const queryUrl = `sheets.html`
await new Promise((resolve, reject) => {
https
.get(queryUrl, res => {
let stream = []
res
.on('data', function(data) {
stream.push(data)
})
.on('end', function() {
let data = Buffer.concat(stream)
data = JSON.parse(data)
sheetsArray.push(data['values'])
resolve();
})
})
.on('error', err => {
reject(err);
})
})
}
formatJsonToLocale(sheetsArray)
}

Categories