Can't use callback in frontend

I’m messing around with the hello world code and I’ve added a function return a callback to a query.

actor testcallback{

  public type CallbackWrapper = 
  {
    callback : shared query () -> async Nat;
  };

  public func greet(name : Text) : async Text {
    return "Hello, " # name # "!";
  };

  public shared query func theCallback() : async Nat
  {
    return 10;
  };

  public shared query func getCallbackWrapper() : async CallbackWrapper
  {
    return {
      callback = theCallback;
    }
  };
};

but when I try to call it in javascript it says that callbackWrapper.callback() is not a function.

const callbackWrapper = await testcallback.getCallbackWrapper();
console.log(callbackWrapper.callback());

How do I import the candid interface for CallbackWrapper into my code?

1 Like

Have you tried updating your js bindings?
You can run dfx deploy again, that should update the js candid files.

Yeah I tried that but it still doesn’t seem to know that callbackWrapper is a function. When I print
typeof callbackWrapper.callback it just says object. However, if I simply print callbackWrapper.callback i get :

(2) [Principal, 'theCallback'] 0: Principal {_arr: Uint8Array(10), _isPrincipal: true} 1: "theCallback" length: 2 [[Prototype]]: Array(0)

But I don’t know what this means.

What are the contents of the .did file?

type CallbackWrapper = record {callback: func () -> (nat) query;};
service : {
  getCallbackWrapper: () -> (CallbackWrapper) query;
  greet: (text) -> (text);
  theCallback: () -> (nat) query;
}


It looks like an array of 2 elements but I’m not sure why.

Perhaps looking at the files in .dfx/local/canisters will reveal something.

Yeah, I realized I can convert the first element to the Principal of the canister and the second element is the name of the method. I guess I could “assemble” the function manually in javascript and call it, but it would’ve been nice if there was a way to abstract it and just call callbackWrapper.callback().

Sounds a bit like JSONP.

@chenyan do you know if this should work?

Yep, you are correct that the callback function in JS is represented as a pair of principal and method name. See Candid Reference | Internet Computer Developer Portal.

You can manually assemble that into a callable function. Feel free to file an issue in the agent-js repo to add this feature.

1 Like