2

I am working with a package called DSBridge to connect a mobile application (iOS code in this case) to javascript code containing the main logic of my application. This involves running the JavaScript on an invisible WKWebView.

My JavaScript code needs to call a method in the native iOS application which needs to execute asynchronously (as to not block the UI), to do this I am using callbacks in JavaScript and a completionHandler in native.

My Objective C function reads:

- (void)read:(NSDictionary *) args :(JSCallback) completionHandler{ dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ NSLog(@"In Read"); while(self->connection != NULL) { if([self->connection isMessageAvailable]) { [self->connection messageRetrieved]; NSLog(@"Message Received in ViewController"); completionHandler([self->connection getMessage], YES); } } }); }

Which is called from my JavaScript here:

function read() {
    data = "reading";
    dsBridge.call("read", data, function (read_result) {
        console.log("read_result = ", read_result)
        return read_result;
        });
}

The issue lies in the JavaScript, I need the JavaScript function 'read' to return the value "read_result" once the Native application returns the message. Right now my code is calling the objective C, which is executing properly and returning the required value to the callback function in the JavaScript but the JavaScript function 'read' already completed without a return value.

Is there a way for me to stall the JavaScript until the callback is complete?

saxford
  • 23
  • 5
  • What is calling the JS `read()` function? Can you return a promise to it? – Mark Jan 14 '19 at 18:05
  • The read function is being called as part of a large codebases logic, usually inside of if statements. I am not familiar with promises but will try them now. – saxford Jan 14 '19 at 18:28
  • Related (not checked if full duplicate): https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323 – freedomn-m Jan 14 '19 at 18:33

1 Answers1

0

You can pass a callback to the read() function and invoke it when the underlying Objective-C code returns

function read(clb) {
  data = "reading";
  dsBridge.call("read", data, function (read_result) {
    clb(read_result);
  });
}

and your caller

read(res => {
  //result available here
  console.log(res);
})

Alternatively with Promises

function read() {
  data = "reading";
  return new Promise(resolve => {
    dsBridge.call("read", data, function (read_result) {
      resolve(read_result);
    });
  });
}

and the caller

read()
  .then(res => {
     //result available here
      console.log(res);
   })
Karim
  • 7,479
  • 1
  • 18
  • 31
  • The read function is being called as part of a large codebases logic, usually inside of if statements. This causes problems with having callbacks in the caller as I will end up with a lot of callbacks, possibly nested. – saxford Jan 14 '19 at 18:23
  • if the objective-c code has to be executed asynchronously i don't see many options a part from using callbacks (as in this example) or promises. – Karim Jan 14 '19 at 18:28