0

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:

  1. With (callback).bind(this) I can probably assign the value to the object.
  2. The value is never shown in the showPaymentInstructionsAction (currently a simple web page), because the page is rendered before the callback function is executed by it's asynchronous nature.

How can you help me?

  1. Do I miss a basic pattern in async programming?

  2. Should I not try to receive a value from a callback?

  3. 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);
};

1 Answer 1

4
  1. Yes you are missing basic pattern here.
  2. Yes, you can not return a value from callback.
  3. You can sure read more about Promise here

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I am trying to get this running. Within Promise I can't access the object with "this", e.g. it won't recognize "this.iota_node".
You can, you can use arrow function here. I edited the code, please take a look. Arrow functions allow you to access outer scope.
You can check one snippet for reference I have kept at end.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.