I am trying to get started with web3.js. There are two different examples for getBlockNumber or getBalance:
web3.eth.getBlockNumber(function (error, result) {
console.log(result);
});
or shorter
web3.eth.getBlockNumber()
.then(console.log);
But how do I save the output to process it further? No matter how I try, I only get "Promise { }".
I have read many posts on this but have not found a solution that works for me.
let result;
const blockNumber = async () => {
result = await web3.eth.getBlockNumber();
};
blockNumber();
Let me know if that solve your problem. Actually "everything" it's a promise in web3 that's why you need async/await
^ console.log the result variable ofc.
Related
getImages() {
const entries_copy = this.state.entries;
entries_copy.map(entry => {
storage.refFromURL(entry.sign_in_photo).getDownloadURL()
.then((url) => {
entry["inPhotoURL"] = url;
storage.refFromURL(entry.sign_out_photo).getDownloadURL()
.then((url) => {
entry["outPhotoURL"] = url;
});
}).catch((error) => {
// Handle any errors
});
});
this.setState({entries: entries_copy});
}
I'm trying to retrieve the download url for images and store them in my entry object inside my entries object array but the problem I'm facing right now is that the setState is called before the urls are retrieved and I have no idea how to wait for it to complete before setting the state. I have searched for similar problems but most of them are solved by executing it inside then() but for mine, I can't execute it inside then() because I have to wait for all the entries to be updated. I have only recently started using React for this project so I'm sorry if the answer is obvious.
This is because the code in asynchronous.
You should call setState inside the .then() function.
I would recommend you to read about Promises in Javascript. They are an important aspect of the language to master.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
In addition to the answer of #TomSlutsky, note that you need to correctly chain your promises and you should not forget to "always return results, otherwise callbacks won't catch the result of a previous promise".
So you need to do as follows:
storage.refFromURL(entry.sign_in_photo).getDownloadURL()
.then((url) => {
entry["inPhotoURL"] = url;
return storage.refFromURL(entry.sign_out_photo).getDownloadURL()
})
.then((url) => {
entry["outPhotoURL"] = url;
this.setState(...);
})
.catch((error) => {
// Handle any errors
});
Note also how the catch() method is called at the end of the chain, see the doc for more details (and possible other options).
I am trying to understand this snipped of code at an intrinsic level:
fetchAllData(){
fetch('http://ec2-x-x-xx-xx.xx-west-x.compute.amazonaws.com:3001/', {mode: "no-cors"})
.then(res => {
return res.json();
})
to better understand a simple component like this:
componentDidMount() {
this.fetchAllData();
}
fetchAllData(){
fetch('http://ecx-x-x-xxx-xx.xx-west-x.compute.amazonaws.com:3001/', {mode: "no-cors"})
.then(res => {
return res.json();
})
.then(resJson => {
this.setState(prevState => {
return{
fetchDataLoaded: true,
fetchData: resJson.data.todolist,
};
});
});
}
When fetching from an API, is the data stored temporarily in the res
=> function and chained on using .then?
If so, how could I visualise (in the console maybe?) the properties of the data fetched?
I find myself in a position where I need to manipulate data pulled from an API I don't know the shape of.
I am new to React and any detailed explanation would help a lot, thank you.
This isn't a react thing at all, but rather plain javascript and promises. fetch returns a resolved promise. The response isn't "saved" in res, per se, but rather is passed to a function where you've named the parameter res. If you want to view the raw response res you can do that in the first chained then, ensuring you still return the json promise for the next thenable.
fetch('http://ec2-3-8-196-93.eu-west-2.compute.amazonaws.com:3001/', {mode: "no-cors"})
.then(res => {
console.log('res', res);
return res.json();
})
Perhaps it would be a little clearer broken down a bit. Factor out the anonymous inline function into a named one, and pass that as the thenable callback. The fetch result isn't really saved anywhere (it is technically in memory in the browser heap, but that's another topic) and is just being passed to a function.
const logResultAndReturnJson = result => {
console.log('result', result);
return result.json();
};
fetch('http://ec2-3-8-196-93.eu-west-2.compute.amazonaws.com:3001/', {mode: "no-cors"})
.then(logResultAndReturnJson)
If you need to manipulate the fetched data, then you likely want to look at the resolved JSON object and not the response object.
In the given example, the variable resJson contains the response body parsed by JSON(i.e. this piece of code only works if the API returns a JSON response).
Adding on to #drew, This .then(...).then(...) is called Promise Chaining. It is a useful way of making a flow where you can process data in stages and then deal with errors in the end.
As Reference, these two pages will surely help
promise-basics
promise-chaining
A node.js (and coding in general) beginner here, struggling with the async nature of node. I'm trying to write some code that will look up the members of certain AD groups and add the member names to an array, as per the "getMembers" function below. I'm only interested in computer objects, which is why I only have ad.find returning "other" objects.
Once that is complete, I want the "processAssets" function to do something with the array - for the purpose of testing, just ouptutting to the console.log. The problem is that "processAssets" is running before "getMembers" has populated the array. What am I doing wrong? I realise the answer may begin with "several things"...!
const ActiveDirectory = require('activedirectory');
var ad = new ActiveDirectory(config);
var query = 'memberOf=cn=';
var cNames = [
'group1',
'group2',
'group3'
];
var baseOu = ',ou=Groups,dc=example,dc=com';
function run(cNames) {
Promise.all(cNames.map(cName => getMembers(cName))).then(processAssets())
}
async function getMembers(cName) {
await ad.find(query + cName + baseOu, async function(err, results) {
if ((err) || (! results)) {return;}
await _.each(results.other, function(other) {
assetArray.push(other.cn);
});
});
}
function processAssets() {
console.log("Contents of assetArray (" + assetArray.length + " assets):");
assetArray.forEach(function(item) {
console.log(item);
});
}
thanks in advance.
You have some things mixed up.
The main problem causing your immediate issue is this line:
Promise.all(cNames.map(cName => getMembers(cName))).then(processAssets())
You need to pass a function to then() which will be called when the promise resolves. You are not doing that, you are passing it the result of calling processAssets(), which has the effect of calling processAssets() immediately. Typically you would us something like:
Promise.all(cNames.map(cName => getMembers(cName))).then(() => processAssets())
/* ^^ pass a function */
Additionally you are await things for no purpose. There's no reason to await here:
await ad.find(query + cName + baseOu, async function(err, results) {
ad.find doesn't return a promise. In general functions that take callbacks don't return promises (maybe there are some exceptions, but I can't think of any). If you want to have a promise to use in run()'s Promise.all you need to wrap the find function in a promise and return it. Something like:
function getMembers(cName) {
return new Promise((resolve, reject) => {
ad.find(query + cName + baseOu, function(err, results) {
if (err) return reject(err)
// I'm making some assumptions about results. But hopefully this gives
// a good enough idea
let data = results.other.map(other => other.cn)
resolve(data)
});
});
}
Now getMembers returns a promise that resolves to the result of ad.find and you can use it in `Promise.all.
my code is:
async getDetails(){
for(var i=0;i<this.results.length;i++){
// this.booking.length=0;
// this.hbl.length=0;
var hblList=[];
var bookingList=[];
await this.api.get("track/dtl",
{
loadPortId: this.results[i].loadPortId,
dischargeId:this.results[i].dischargeId,
scheduleId: this.results[i].scheduleId
})
.subscribe(res1 => {
//let resp1 = res1;
this.details= res1;
bookingList.length=0;
hblList.length=0;
for(var j=0;j<this.details.length;j++){
if(this.details[j].bookNo!== undefined){
bookingList.push(this.details[j]);
}else if(this.details[j].hblNo!== undefined){
hblList.push(this.details[j]);
}
}
// this.results[i]["hbl"]=this.hbl;
// this.results[i]["booking"]=this.booking;
console.log("this.hbl inside subscribe::::::::::::"+hblList);
console.log("this.booking inside subscribe::::::::::::"+bookingList);
console.log("this.results[i] after::::::::::::"+this.results[i]);
});
this.results[i]["hbl"]=hblList;
this.results[i]["booking"]=bookingList;
console.log("this.hbl after::::::::::::"+hblList);
console.log("this.booking after::::::::::::"+bookingList);
console.log("this.results[i] after::::::::::::"+this.results[i]);
this.getCurrent(this.results[i].queries[0]);
}
}
I want to make async call for each for loop item. could anyone please help me to use async-await to make sure the first and every async call is completed prior to the next call.
Thanks in advance
As you are subscribing in the Observable you're not using the async/await approach. Async/await works only with Promises, so, you need to transform your observable to promise first.
I don't know how your this.api works, but, maybe, you should have a toPromise() function. Using await you won't need to subscribe or to use ".then()" promise function.
I have no means of trying your code or trying mine, but here, take a look at this one that should work in theory.
The main point is: you have to decide whether to use Observables or to use Promises. Unfortunately the Angular team decided to return Observables in their http module. Observables do not work with async await, but there is a simple conversion: Observable.prototype.toPromise(). Use that, and get rid of .subscribe.
async getDetails(){
for(var i=0;i<this.results.length;i++){
// this.booking.length=0;
// this.hbl.length=0;
var hblList=[];
var bookingList=[];
var res1 = await this.api.get("track/dtl", {
loadPortId: this.results[i].loadPortId,
dischargeId:this.results[i].dischargeId,
scheduleId: this.results[i].scheduleId
}).toPromise();
this.details= res1;
bookingList.length=0;
hblList.length=0;
for(var j=0;j<this.details.length;j++){
if(this.details[j].bookNo!== undefined){
bookingList.push(this.details[j]);
} else if(this.details[j].hblNo!== undefined){
hblList.push(this.details[j]);
}
}
this.results[i]["hbl"] = hblList;
this.results[i]["booking"] = bookingList;
console.log("this.hbl after::::::::::::"+hblList);
console.log("this.booking after::::::::::::"+bookingList);
console.log("this.results[i] after::::::::::::"+this.results[i]);
this.getCurrent(this.results[i].queries[0]);
}
}
I've got this code:
var me = Restangular.one('object', 1).get({params:params});
me.then(function (data) {
$scope.me = data;
$scope.loadsubobject();
});
$scope.loadsubobject = function () {
$scope.me.getList("subobject")
.then(function(subobject) {
//the code never gets here
console.log('loaded subobjects', subobjects);
$scope.subobjects = $scope.subobjects.concat(subobject.results);
if (data.next){
$scope.next = data.next;
}
},function(response){
console.log('Error with response:', response.status)
});
when I try to debug the code It seems that after calling the $scope.me.getList("subobject")It returns to the first thenand never getting to the second then, the one that actually process the subobjects I need.
Any clue out of call back hell?
I verified that the server does return the correct answer
How can I fix that? be glad for help with this
turned out to be a completely different issue, the json returned wasn't "flat", so I need to use a responseExtractor as explained here