Reputation: 125
I am trying to write a short app for testing IOTA nano transactions. When it comes to asynchronous programming, I am a noob. Please forgive me for not seeing the obvious.
My problem: How to assign a value from a callback function to an object at the right moment.
Explanation of the code below: Those are fragments from my nodejs express app. I use a controller, router and my wallet model.
When requesting a service (iri) using the iota library I have only asynchronous functions at my disposal. In the case below, I want to receive an IOTA address for my wallet. This works well with the service, I can test it by writing the generated address to the console.log.
However, probably because the callback function is executed after all other functions, I just can't find a way to write this to my wallet object and receive it for displaying it in my showPaymentInstructionsAction.
My explanation so far:
How can you help me?
Do I miss a basic pattern in async programming?
Should I not try to receive a value from a callback?
Should I learn about Promise to solve this?
Best Regards, Peterobjec
'use strict'
class Wallet{
constructor(iota_node, seed){
this.seed = seed;
this.receivingAddress = "empty";
this.iota_node = iota_node;
}
generateAddress() {
this.iota_node.api.getNewAddress(this.seed, {'checksum': true}, postResponse)
function postResponse(error,address) {
if (!error) {
// callback won't assigned to my wallet object.
// I can probably use (function).bind(this);
// But this doesn't solve the timing issue
this.receivingAddress = address
// console.log shows, the address is generated correctly
// but how can I get it into my object? and retreive it after it is written?
console.log("address callback: %s", this.receivingAddress)
}else{
console.log(e.message);
}
}
}
getReceivingAddress(){
// I never managed to get this filled by the callback
console.log("in getReceivingAddress: %s", this.receivingAddress)
return this.receivingAddress;
}
}
// The controller
var config = require('../config.js'),
Wallet = require('./model_wallet'),
IOTA = require('iota.lib.js');
function orderRequestAction(req, res, next){
// IOTA Reference Implementation
var iri = new IOTA({
'host': 'http://localhost',
'port': 14265
});
res.locals.wallet = new Wallet(iri, config.wallet.seed);
res.locals.wallet.generateAddress()
}
function showPaymentInstructionsAction(req, res){
res.render('paymentInstructions', {
title:"payment instructions",
receivingAddress: res.locals.wallet.getReceivingAddress()
})
}
// Router
var controller = require('./controller');
module.exports = function(app){
app.post('/orderRequest', controller.orderRequestAction, controller.showPaymentInstructionsAction);
};
Upvotes: 0
Views: 1282
Reputation: 261
You can remove getReceivingAddress function and use generateAddress() like this,
generateAddress() {
return new Promise((resolve, reject) => {
this.iota_node.api.getNewAddress(this.seed, {'checksum': true}, (error,address) => {
if (!error) {
// callback won't assigned to my wallet object.
// I can probably use (function).bind(this);
// But this doesn't solve the timing issue
this.receivingAddress = address
// console.log shows, the address is generated correctly
// but how can I get it into my object? and retreive it after it is written?
console.log("address callback: %s", this.receivingAddress)
resolve(address); // You will get this while calling this function as shown next
}else{
console.log(e.message);
reject(error);
}
})
})
}
Now while calling the function, you need to use it like this wherever you need to call,
...
generateRecievingAddress().then(function(address){
// here address is what you resolved earlier
}).catch(function(error){
// error is what you rejected
})
I hope this will clarify your doubts.
When you familiar with Promises, you might want to use es7 syntax for writing async code, using async and await. You can also read more about it here
Demo snippet
class XYZ {
constructor() {
this.x = 15;
}
getX() {
return new Promise((resolve, reject) => {
if(true){
resolve(this.x); // inside Promise
}
else{
reject(new Error("This is error"));
}
})
}
}
const xObj = new XYZ();
xObj.getX().then(function(x){
console.log(x);
}).catch(function(){
console.log(error);
})
This will log 15.
Upvotes: 4