async function not waiting to move on - reactjs

I have a react app, in which im hiding and showing buttons instead of moving across pages, before I show the next button I want to make sure the function the button was meant to call has completed. Here is what I have so far:
This is the Async function:
async handleTransferFromEthereum(){
parseAddress(this.state.sc)
this.setState(prevState => ({
isEthTransferVisible: !prevState.isEthTransferVisible,
isGoDeployedVisible: !prevState.isGoDeployedVisible
}));
}
and this would be the function im calling:
import ERC20ABI from './blockchain/ERC20ABI.js';
import ethweb3 from './blockchain/ethweb3.js';
import _ from 'lodash';
var addressesValues = [];
var uniqueAddresses = [];
var values = [];
var count = 0;
var map = {};
var address =[];
var amounts=[];
var choppedAdrresses = [];
export function parseAddress(_smartcontract){
console.log("Scanning blockchain")
var contractObj = new ethweb3.eth.Contract(ERC20ABI,_smartcontract);
contractObj.getPastEvents(
'Transfer' || 'allEvents',
{
fromBlock: 0,
toBlock: 'latest'
},
function(err,res){
for(var i =1; i< res.length; i++){
if (uniqueAddresses.includes(res[i].returnValues.from)===false) {
uniqueAddresses[count] = res[i].returnValues.from;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
if (uniqueAddresses.includes(res[i].returnValues.to)===false){
uniqueAddresses[count] = res[i].returnValues.to;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
}
for(var j = 0; j< res.length; j++){
map[res[j].returnValues.from] -= parseInt(res[j].returnValues.value);
map[res[j].returnValues.to] += parseInt(res[j].returnValues.value);
}
for(var x = 0; x < uniqueAddresses.length; x++){
addressesValues.push([uniqueAddresses[x], parseInt(map[res[x].returnValues.to])])
}
for(var y=0; y < addressesValues.length; y++){
address.push(addressesValues[y][0]);
amounts.push(addressesValues[y][1]);
}
var choppedAdrresses=_.chunk(address, 100);
var choppedValue=_.chunk(amounts, 100);
var tokenSum = amounts.reduce((a, b) => a + b, 0);
sessionStorage.setItem("addresses", JSON.stringify(address))
sessionStorage.setItem("tokenSum", JSON.stringify(tokenSum))
sessionStorage.setItem("choppedAdrresses", JSON.stringify(choppedAdrresses))
sessionStorage.setItem("choppedValue", JSON.stringify(choppedValue))
}
);
}
Any pointers would really help.

You need to wait on a promise, but since the getPastEvents function works in a callback pattern, you could create a custom promise and return it from parseAddress method
export function parseAddress(_smartcontract){
console.log("Scanning blockchain")
return new Promise(function(resolve, reject) {
var contractObj = new ethweb3.eth.Contract(ERC20ABI,_smartcontract);
contractObj.getPastEvents(
'Transfer' || 'allEvents',
{
fromBlock: 0,
toBlock: 'latest'
},
function(err,res){
if (err) {
reject(err);
}
for(var i =1; i< res.length; i++){
if (uniqueAddresses.includes(res[i].returnValues.from)===false) {
uniqueAddresses[count] = res[i].returnValues.from;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
if (uniqueAddresses.includes(res[i].returnValues.to)===false){
uniqueAddresses[count] = res[i].returnValues.to;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
}
for(var j = 0; j< res.length; j++){
map[res[j].returnValues.from] -= parseInt(res[j].returnValues.value);
map[res[j].returnValues.to] += parseInt(res[j].returnValues.value);
}
for(var x = 0; x < uniqueAddresses.length; x++){
addressesValues.push([uniqueAddresses[x], parseInt(map[res[x].returnValues.to])])
}
for(var y=0; y < addressesValues.length; y++){
address.push(addressesValues[y][0]);
amounts.push(addressesValues[y][1]);
}
var choppedAdrresses=_.chunk(address, 100);
var choppedValue=_.chunk(amounts, 100);
var tokenSum = amounts.reduce((a, b) => a + b, 0);
sessionStorage.setItem("addresses", JSON.stringify(address))
sessionStorage.setItem("tokenSum", JSON.stringify(tokenSum))
sessionStorage.setItem("choppedAdrresses", JSON.stringify(choppedAdrresses))
sessionStorage.setItem("choppedValue", JSON.stringify(choppedValue))
resolve();
}
);
});
}
After this, you can use await like
async handleTransferFromEthereum(){
await parseAddress(this.state.sc)
this.setState(prevState => ({
isEthTransferVisible: !prevState.isEthTransferVisible,
isGoDeployedVisible: !prevState.isGoDeployedVisible
}));
}
However if its possible try to convert getPastEvents so that it returns a promise instead of using a callback

The promise starts when you create it and await will wait for it to resolve. But the code in the middle of these two statements will run before the promise ends. If you don't need any result of the promise you can put code in that zone to paralelize the execution of it with the promise.
const timeBomb = (resolve, reject) => {
const msleft = Math.random() * 700 + 200;
console.log("Countdown started!");
console.log("Only "+(Math.round(msleft)/1000)+" seconds left!!");
setTimeout(resolve, msleft);
};
waiter = async (p) => {
console.log("I will hurry to do my last wish before dying");
const result = await p;
console.log("It Exploded!");
}
waiter(new Promise(timeBomb));

Related

tinymce unable to bind correctly nestedmenuitem

I have the following code written and I am not sure why the second level menu items are always the same for each primary level. I know this might be related with scope variables. Can you please suggest an alternative?
``
editor.ui.registry.addMenuButton(insertFields, {
text: My button,
fetch: function (callback) {
var temp = [];
for(var i = 0; i < k.state.ListItems.length; i++)
{
var obj = {};
var fieldItems = k.state.ListItems[i].description;
console.log(fieldItems);
obj["text"] = k.state.ListItems[i].Title;
obj["type"] = "nestedmenuitem";
obj["getSubmenuItems"] = () => {
console.log("fired for submenu");
var getMenuItem = t => {
return {
type: "menuitem",
text: t,
onAction: () => {
editor.insertContent("{{ " + t + "}}");
}
};
};
var nestedItems = [];
for (let k = 0; k < fieldItems.length; k++) {
nestedItems.push(getMenuItem(fieldItems[k].Title ));
}
return nestedItems;
}
temp.push(obj);
console.log(temp);
}
console.log(temp);
var items = temp;
callback(items);
}
});
}
}}
/>
was able to resolve this issue. Not sure if there was a better way.
setup: function (editor) {
for(let i = 0; i < k.state.ListItems.length;i++)
{
// let Fields = k.state.ListItems[i].Fields;
editor.ui.registry.addNestedMenuItem(k.state.ListItems[i].Id, {
text: k.state.ListItems[i].Title,
getSubmenuItems: () => {
var getMenuItem = (t,r) => {
return {
type: "menuitem",
text: t,
onAction: () => {
editor.insertContent("{{" + r +"|" + t + "}}");
}
};
};
var nestedItems = [];
for (let j = 0; j < k.state.ListItems[i].Fields.length; j++) {
// console.log(Fields[j].Title);
nestedItems.push(getMenuItem(k.state.ListItems[i].Fields[j].Title,k.state.ListItems[i].Title));
}
return nestedItems;
}
});
}
}

How can I do to aggregate count function return a number not an array

I try to count number of each article but the result is not what I want
This is my code
var nameWebsites = await Article.distinct("website.name");
var idWebsites = await Article.distinct("website.id");
var numberArticle = [];
var result = [];
for(var i = 0; i < nameWebsites.length; i++) {
await Article.aggregate([
{ $match: {"website.id": idWebsites[i]}},
{ $count: "count"}
], function(err, result){
numberArticle.push(result);
});
}
for(var i = 0; i < nameWebsites.length; i++) {
result.push({"id":idWebsites[i], "name":nameWebsites[i], "number_article": numberArticle[i]});
}
And this is a part of result
{"data":[{"id":1,"name":"Dan tri","number_article":[{"count":52952}]},...]}
I want the result like:
{"data":[{"id":1,"name":"Dân trí","number_article":52952},...]}
Instead of grabbing the entire results of numberArticle[i], get the just count of the first object in the array.
for(var i = 0; i < nameWebsites.length; i++) {
result.push({
id: idWebsites[i],
name: nameWebsites[i],
number_article: numberArticle[i][0].count,
});
}
var objectArray = {"data":[{"id":1,"name":"Dân trí","number_article":52952}]}
Then you can use
objectArray.data.length

Don't know why i get React Maximum call stack size exceeded

When i use the function in funkFiltriranje inside filtriranje everything works fine:
export default class Vraboteni extends Component {
constructor(props) {
super(props);
this.filtriranje = this.filtriranje.bind(this);
this.funkFiltriranje = this.filtriranje.bind(this);
}
//i'm calling filtriranje(e) by <Form onSubmit={this.filtriranje}>
filtriranje(e){
e.preventDefault();
var arr1 = [{embg: 'gad'},{embg: 'gadipol'},{embg: 'tri'}];
var arr2 = [{embg: 'gad'},{embg: 'bljat'}];
var arr = arr1.filter(function(n) {
for(var i=0; i < arr2.length; i++){
if(n.embg === arr2[i].embg){
return true;
}
}
return false;
});
console.log(arr);
}
}
But when i code it like this it gets an error:
RangeError: Maximum call stack size exceeded
at Vraboteni.filtriranje (Vraboteni.js:72)
funkFiltriranje(e,arr1,arr2){
var arr = arr1.filter(function(n) {
for(var i=0; i < arr2.length; i++){
if(n.embg === arr2[i].embg){
return true;
}
}
return false;
});
return arr;
}
filtriranje(e){
e.preventDefault();
var arr1 = [{embg: 'gad'},{embg: 'gadipol'},{embg: 'tri'}];
var arr2 = [{embg: 'gad'},{embg: 'bljat'}];
var arr3 = this.funkFiltriranje(e,arr1,arr2);
}
Can somebody tell me why?
funkFiltriranje = (e,arr1,arr2) => {
var arr = arr1.filter(function(n) {
for(var i=0; i < arr2.length; i++){
if(n.embg === arr2[i].embg){
return true;
}
}
return false;
});
return arr;
}
filtriranje = (e) => {
e.preventDefault();
var arr1 = [{embg: 'gad'},{embg: 'gadipol'},{embg: 'tri'}];
var arr2 = [{embg: 'gad'},{embg: 'bljat'}];
var arr3 = this.funkFiltriranje(e,arr1,arr2);
}
Change
onSubmit={this.filtriranje} //this gets called on every render without user interaction
To
onSubmit ={e => this.filtriranje(e)} //this gets called only when you click on a button or user interaction
This way onSubmit only triggers when there is user interaction like when you click on submit button for eg.

Need to use that counter variable outside since if i am calling that function am not getting output return

checkGridData(name: string, searchObj: ElementArrayFinder) {
if (name != "") {
let counter = 0;
let beforesplit = name;
let aftersplit = beforesplit.split("|");
var countval = searchObj.count();
return searchObj.count().then((count) => {
for (let i = 0; i < aftersplit.length; i++) {
let countval = searchObj.count();
// expect(count).toBe(expectedRecords[i]);
for (let j = 0; j < count; j++) {
searchObj.get(j).getText().then(function (text) {
if (text.indexOf(aftersplit[i]) !== -1) {
expect(text).toContain(aftersplit[i]);
++counter
//console.log("counter inside loop is" + counter)
}
return counter;
});
}
}
});
}
}
I am new to protractore. I wrote a function below
I am calling this in another function.
var abc = this.CheckGridData(ProductData.AddEquipment.EquipmentSelection, ProductObj.ele_equipmentvalidation)
console.log("Counter value returned:" + abc)
And i am getting this error
Counter value returned:ManagedPromise::5760 {[[PromiseStatus]]: "pending"}
I tried to do promise but I don't know how to do resolve promise. How to resolve inside for loop in the above, so that i can use it and know the concept? I tried various site but i couldn't understand how to resolve.
Because the function CheckGridData return a promise, so the variable abc is a promise.
To consume the eventual value of promise, you have to use then() as below:
checkGridData(name: string, searchObj: ElementArrayFinder) {
if (name != "") {
let counter = 0;
let beforesplit = name;
let aftersplit = beforesplit.split("|");
return searchObj.getText().then((texts) => {
// texts is an string array of text of all elements of searchObj
for (let i = 0; i < aftersplit.length; i++) {
if(texts.includes(aftersplit[i])) {
++counter;
}
}
return counter;
};
}
}
var abc = this.CheckGridData(ProductData.AddEquipment.EquipmentSelection,
ProductObj.ele_equipmentvalidation)
abc.then(function(count){
console.log(count);
})

nightmare how to looply select the selector

var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
var fs = require('fs');
var result;
nightmare
.goto('http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=')
.wait('select[name="selectTeam"]')
.evaluate(function () {
var options = document.querySelectorAll('option'),i;
var values =[]
for (i = 1; i < options.length; ++i) {
values.push(options[i].value)
}
return values;
})
.then(function (values) {
console.log(values)
values.reduce(function(accumulator, value) {
return accumulator.then(function(results) {
return nightmare.goto("http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=")
.wait('select[name="selectTeam"]')
.select('select[name="selectTeam"]', value)
.wait('button[onClick="selectData();"]')
.click('button[onClick="selectData();"]')
.wait('table[class="tableOutputDate"]')
.evaluate(function () {
return document.querySelector('table[class="tableOutputDate"]').textContent;
})
.then(function(result){
console.log(result)
results.push(result);
return results;
});
});
}, Promise.resolve([])).then(function(results){
console.log(results)
});
})
.catch(function (error) {
console.error('Search failed:', error);
});
That is my code .I want to looping select all the selector in that page and get the all html data.I asked a question in here that how to loop in nightmare,but that result cant solve this problem.please help me. Thank you.
I solve my question.the problem is happened in the deal time,not in the loop logic.I add some more wait(time).I think wait(time)is better than the wait(selector).so is over. thank u attention.
var run = function * () {
//var values = ['http://www.yahoo.com', 'http://example.com', 'http://w3c.org'];
var titles = [];
for (var i = 0; i < values.length; i++) {
var title = yield nightmare.goto('.............')
//.wait('select[name="selectTeam"]')
.wait(2000)
.select('select[name="selectTeam"]', values[i])
.wait(2000)
.click('button[onClick="selectData();"]')
//.wait('table[class="tableOutputDate"]')
.wait(2000)
.evaluate(function () {
//return document.querySelector('table[class="tableOutputDate"]').textContent;
var divs = document.querySelectorAll('table[class="tableOutputDate"]'),i;
var tables = []
for (i = 0; i < divs.length; ++i) {
tables.push(divs[i].textContent)
//result += divs[i].href.toString()+"\n";
}
return tables;
})
titles.push(title);
}
return titles;
}
vo(run)(function(err, titles) {
console.dir(titles);
});

Resources