using key of an object in single line - javascript

Below is a simple programme which includes web3 :-
let web3 = require('web3');
var real = new web3(web3.givenProvider) // web3.givenProvider is having value of my infura endpoint
discuss();
async function discuss()
{
let dif = await real.eth.getBlock(16532022)
let di = dif.size
console.log(di) // Line 1 :- displays the size
console.log(typeof dif ) // Line 2 :- returns object
let diftwo = await real.eth.getBlock(16532022).size ;
console.log(diftwo) ; // Line 3 :- displays undefined
When I used the .size directly in Line 3 it is not showing the size of block. I checked the typeof of the .getBlock and saw that it is an object which means size is key of that object. So why is it not showing the result when I used the size using the dot notation.
Can anyone please tell me what am I doing wrong ?
As per me , using dot notation should have given me the result.

You have to do
let diftwo = (await real.eth.getBlock(16532022)).size
You have to wait for the promise to resolve and then try to get the size field from it.
Quick example you can try in terminal
let func = () => new Promise((res, rej) => {
return setTimeout(() => res({result: true}), 2000)
})
await func() // This would resolve to {result: true}
await func().result // This would return undefined cause the promise is not resolved yet
(await func()).result //This would return true as promise is resolved first
Note: For the example, assuming that you have top level await

Related

Using await with replaceAll's callback function

I am trying out a Chrome extension.
How do I get a replaceAll's callback function to use await ?
window.onload = async () =>
{
const elem = document.getElementById('#myID');
const elem_modified = elem.replaceAll(regex, await myFunction);
document.getElementById('#myID').innerHTML = elem_modified;
}
myFunction :
const myFunction = async (str) =>
{
const items = [...str.matchAll(regex)][0];
// Do some manipulation
let amount = number * value;
const amount_modified = await calculate(amount);
console.log("amount_modified = " + amount_modified); // This shows correctly
return items[0] + ' (' + amount_modified + ')';
}
The result is like
over [object Promise] to many people
You don't, replaceAll — like lots of functions that support callbacks — doesn't expect a promise as a return value from the callback. In the vast majority of cases, you can't usefully pass a promise to code that doesn't expect one. (map is one exception to that rule.)
You haven't provided a runnable example or an example of your regular expression, but the general shape of the solution here will be:
Split the string into parts (the segments you want to pass through your async function and the segments between them).
Start the calculation for each of the segments you want to process and get a promise (from your async function) of the result; for the segments in-between, just create a promise fulfilled to the original segment value.
Wait for all of those to complete by using Promise.all, awaiting the promise it provides. (That's assuming it's okay to start processing all the segments at once, rather than waiting for the processing of one to end before starting processing the next.)
Assemble a new string from the updated segments and the segments that used to be between them.
Here's a rough sketch that isolates the numbers in a string and builds a new string with the numbers doubled. This version doesn't, of course, need to be async at all, but you can substitute a truly async operation for calculate:
async function calculate(str) {
await new Promise((resolve) => setTimeout(resolve, 10)); // Just so we do actually do something async
return str ? String(Number(str) * 2) : str;
}
async function example(str) {
const rex1 = /(\d+)/; // Note the capture group, so `split` retains the delimiter between matches
const rex2 = /^\d+$/; // Same as above, but full string match and no capture group
// #1
const parts = str.split(rex1);
// #2 and #3 (the `await`)
const updated = await Promise.all(parts.map(async (part) => {
if (rex2.test(part)) {
return await calculate(part);
}
return part;
}));
// #4
return updated.join("");
}
example("Testing 1 2 3 testing")
.then((result) => console.log(result))
.catch((error) => console.error(error));
Side note: The DOM event system won't pay any attention to the promise the async function you're using as an event handler returns, so it's important not to allow any errors (promise rejections) to terminate that handler, since those rejections will be unhandled.

There are 2 identical receive values ​from a promise: in one case it works, in another it gives an TypeError: x is not a function

I use the element search in my autotest and take the name from the list. My code works, everything is fine. But in autotest I use this code several times. Therefore, I decided to put it into a function and call it when I need to.
Code operates:
await driver.wait(until.elementLocated(By.className("item")), 20000);
let findItems1 = await driver.findElements(By.className("item"));
let items1 = findItems1.map(async elem => await elem.getText());
await Promise.all(items1);
let currentItem1 = findItems1[findItems1.length - 1];
await currentItem1.click();
currentName = await currentItem1.getText(); // This string operates
await Promise.all(currentName)
console.log(currentName)
I infer the value of the variable from the function in which the promise lies. I can click on this item. But when I want to get a text value from a promise, the string "currentName = await currentItem1.getText()" throws an error. Although in my first code this line works. I don’t understand what could be the reason.
Code doesn't operate:
async function findCurrentItem(){
await driver.wait(until.elementLocated(By.className("item")), 20000);
let findItems = await driver.findElements(By.className("item"));
let items = findItems.map(async elem => await elem.getText());
await Promise.all(items);
let currentItem = findItems[findItems.length - 1];
return currentItem;
}
let current = findCurrentItem();
await currentItem1.click();
console.log(current, 1) // console displays promise
let currentName = await current.getText(); // This string doesn't operate
await Promise.all(currentName)
console.log(currentName, 2) // console displays error
Error:
TypeError: currentItem.getText is not a function
What can I do?
You made findCurrentItem async function but don't await its result when using it.
Change to let current = await findCurrentItem();

Using returned values in async await in another function

So I am trying to access thermostatRow and the consts defined within it in another function, and I am trying to test that it is working by logging the const within that function so I know I can break it down into its different parts and push those parts into arrays as needed.
I tried 3 things, 2 of them are in my below code examples and the 3rd one returned Promise { <pending> } but I can't find that example.
const worksheet = workbook.getWorksheet("sheet1");
// worksheet is defined in another function earlier in the file that is called asynchronously before this one.
async function dataFormat(worksheet) {
csvWorkbook = workbook.csv.readFile("./uploads/uploadedFile.csv");
await csvWorkbook.then(async function() {
let restarts = 0;
let nullCounts = true;
let thermostatRows = [];
// don't create arrays of current temp here ! do it in a diff function
// const [serial,date,startDate,endDate,thing3,thing4,thing5] = firstTemps
worksheet.eachRow({ includeEmpty: true }, function(row, rowNumber) {
if (rowNumber > 6) {
thermostatRows.push((row.values));
}
});
thermostatRows.map(thermostatRow => {
[,date,time,SystemSetting,systemMode,calendarEvent,ProgramMode,coolSetTemp,HeatSetTemp,currentTemp,currentHumidity,outdoorTemp,windSpeed,coolStage1,HeatStage1,Fan,DMOffset,thermostatTemperature,thermostatHumidity,thermostatMotion] = thermostatRow
return thermostatRow// Push current temps , heatset and cool set into seperate arrays and use those arrays to run the overheat() function
})
})
};
const dataResult = async (worksheet) => {
let result = await dataFormat(worksheet);
console.log(result);
}
This logs nothing.
So I also tried:
const dataResult = async () => {
let result = await dataFormat();
console.log(result);
}
dataResult()
And got this error:
(node:11059) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'eachRow' of undefined
at /Users/jasonharder/coding/projects/hvacdoctor/controllers/hvacdoctor.js:69:15
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
What is happening that I am missing?
Note: I have refactored the code a little bit - I am returning undefined now.
Note: Appended where worksheet is defined (it is defined in the file)

Promise returning undefined and status pending

I'm adding some functions to an Angular App and here is the thing: I'm trying to use a function that creates a promise to get data from the server, but every time I try to use it, it returns undefined. I've "debugged" with console.log printing my variable with the result of my function as value and it prints Promise{'pending'}
Here is the function of the promise and the variable I'm trying to assign.
all_allies(text = ''){
return new Promise((resolve, reject) => {
const _text = text ? /${text} : ''
const path = `${this.env.apiPath}/all_allies${_text}`
this.$http
.get(path)
.then(response => {
const { data } = response
resolve(data)
return data;
})
.catch(error => reject(error))
})
Variable
let allies = this.AliadosFactory.all_allies();
As you can see the function and the variable are in different scripts.
I've tried using await reserved word but still doesn't work
Can you try this method?
let allies = await this.AliadosFactory.all_allies();
console.log(allies);
or like this?
this.AliadosFactory.all_allies().then(allies => console.log(allies);
I sure it should work,
Hope this helps.
Have nice day :)
That's because when you perform assignment the Promise is not resolved / rejected yet.
There are two simple solutions:
1. Using then()
this.AliadosFactory.all_allies().then(result => console.log(result));
2. Using async/await
(note that you need an async method in your class)
async foo() {
let allies = await this.AliadosFactory.all_allies();
console.log(allies);
}
Also in all_allies() you don't need to return the value after calling the resolve() method;

Assert presence of text in an html tag attribute using Puppeteer, Mocha and Chai

I'm beginning my journey with these technologies (including Javascript), so, a beginners question. I'm struggling to work out how to assert that the given text within an HTML attribute is as expected.
The HTML snippet:
<input name="8hv3a" type="radio" id="email-optout-8hv3a" value="1|optin|out" data-com.user-edited="yes">
Here is my .it function thus far, using Mochai, Puppeteer and Chai (setup and teardown elided for clarity:
it('opt out of email', async function () {
await page.setDefaultNavigationTimeout();
await page.waitForSelector('.widget-title');
const frame = page.frames().find(frame => frame.name() === 'iframe');
const emailOptOutButton = await frame.$('#email-optout-8hv3a');
await emailOptOutButton.click();
const emailOptOutConfirmedValue = await frame.$('#email-optout-8hv3a', e => e.getAttribute('data-com.user-edited'))
expect(emailOptOutConfirmedValue).to.include('yes')
})
Everything works up until the click event, but my assertion is clearly wrong. The error is:
AssertionError: object tested must be an array, a map, an object, a set, a string, or a weakset, but object given
I've tried
it('opt out of email', async function () {
await page.setDefaultNavigationTimeout();
await page.waitForSelector('.widget-title');
const frame = page.frames().find(frame => frame.name() === 'iframe');
const emailOptOutButton = await frame.$('#email-optout-8hv3a');
await emailOptOutButton.click();
await page.$eval.emailOptOutConfirmedValue.getAttribute('data-com.user-edited')
expect(emailOptOutConfirmedValue).to.include('yes')
})
Which gives:
TypeError: Cannot read property 'getAttribute' of undefined
And also:
it('opt out of email', async function () {
await page.setDefaultNavigationTimeout();
await page.waitForSelector('.widget-title');
const frame = page.frames().find(frame => frame.name() === 'iframe');
const emailOptOutButton = await frame.$('#email-optout-8hv3a');
await emailOptOutButton.click();
const emailOptOutConfirmedValue = await frame.$('#email-optout-8hv3a', e => e.getAttribute('data-com.user-edited'))
assert.equal(emailOptOutConfirmedValue, 'yes')
})
Which gives:
ReferenceError: assert is not defined
As I said, I'm a beginner so go any help appreciated!
This code is wrong:
const emailOptOutConfirmedValue = await frame.$('#email-optout-8hv3a', e => e.getAttribute('data-com.user-edited'))
expect(emailOptOutConfirmedValue).to.include('yes')
You're using frame.$(selector). Notice how it takes only one argument. The second argument is ignored and your call returns a handle to a DOM element, which causes the expect(...).to.include(...) to fail with a complaint that it cannot test that thing.
You should use frame.$eval(selector, pageFunction[, ...args])
instead. This call will call the function passed as a second argument on the result of applying the selector. So the code should be:
const emailOptOutConfirmedValue = await frame.$eval('#email-optout-8hv3a', e => e.getAttribute('data-com.user-edited'))
expect(emailOptOutConfirmedValue).to.include('yes')
I've left your test intact above, but it seems to me what you'd be looking for here is for a specific value for the attribute, so I'd use this test:
expect(emailOptOutConfirmedValue).to.equal('yes')
The inclusion test would pass if the attribute's value is baryesfoo.

Categories

Resources