Вызов анонимной функции Javascript из кода Dart

Я пишу библиотеку Dart, которая вызывается из JavaScript, и по завершении Dart должен вызвать анонимную функцию обратного вызова, которая находится внутри JavaScript.

JavaScript:

function main() {
    application.log("ready");
}

function getValueById(id){
    return document.getElementById(id).value;
}

function contact(){
    application.log("Contact Submit Clicked");
    application.contact({
        name: getValueById("contactFormName"),
        email: getValueById("contactFormEmail"),
        phone: getValueById("contactFormPhone"),
        message: getValueById("contactFormMessage"),
        subject: "Message From " + getValueById("contactFormName") + " via Contact Form",
        callback: function(response){
            // TODO: handle response here
            console.log("callback being executed");
            console.log(response);
        }
    });
}

var application = function () {
    this.companyId = "5905063580";
    this.companyName = "Company XYZ";
    this.ready = main;
}

HTML:

....
<button onclick="contact()">Submit</button>

Дарт:

import 'dart:html';
import 'dart:js';
...

contact(ContactRequest request, callback)  {
  new RPC.submit(request, URL.contactURL, request.companyName, (res) {
    ContactResponse response = new ContactResponse();
    response.fromJson(res);

    print(response.toString());        
    // prints {"message":"Message Sent", ...}

    // do callback here
    // context.callMethod(callback, [response]); <-- failing here
    // callback(response); <-- also failing


  });
}

void main() {

  String companyId = null;
  String companyName = null;

  context['application']['log'] = (String param) {
    print(param);
  };

  context['application']['contact'] = (JsObject param) {
    ContactRequest request = new ContactRequest();
    request.companyId = companyId;
    request.companyName = companyName;
    request.action = "CONTACT";
    request.name = param["name"];
    request.email = param["email"];
    request.phone = param["phone"];
    request.message = param["message"];
    request.subject = param["subject"];
    contact(request, param["callback"]);
  };

  ...

  var application = new JsObject(context['application']);
  companyId = application['companyId'];
  companyName = application["companyName"];
  application.callMethod("ready");
}

JavaScript успешно вызывает контакт метода Dart, Dart успешно взаимодействует с бэкэндом Java, который отвечает Json, теперь последний шаг для Dart — вызвать обратный вызов, который был отправлен ему, вот где он терпит неудачу и где я не могу понять, как заставить его работать.

если я делаю обратный вызов (ответ), это исключение, которое я получаю:

Exception: Uncaught Error: Class 'JsFunction' has no instance method 'call'.

NoSuchMethodError: method not found: 'call'
Receiver: Instance of 'JsFunction'
Arguments: [Instance of 'ContactResponse']
Stack Trace:
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
#1      contact.<anonymous closure> (http://localhost:63342/jsapi/web/cloudauctioneers.v1.dart:24:13)
#2      RPC.RPC.submit.<anonymous closure> (package:jsapi/model/rpc.dart:10:17)
#3      _RootZone.runUnary (dart:async/zone.dart:1155)
#4      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#5      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#6      _Future._completeWithValue (dart:async/future_impl.dart:358)
#7      _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:412)
#8      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#9      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#10     _handleMutation (dart:html:41819)
 undefined:1undefined

Это также терпит неудачу: JsFunction.callMethod(callback, [response]);

Exception: Uncaught Error: No static method 'callMethod' declared in class 'JsFunction'.

NoSuchMethodError: method not found: 'callMethod'
Receiver: Type: class 'JsFunction'
Arguments: [Instance of 'JsFunction', Instance(length:1) of '_GrowableList']
Stack Trace:
#0      NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:173)
#1      contact.<anonymous closure> (http://localhost:63342/jsapi/web/cloudauctioneers.v1.dart:26:16)
#2      RPC.RPC.submit.<anonymous closure> (package:jsapi/model/rpc.dart:10:17)
#3      _RootZone.runUnary (dart:async/zone.dart:1155)
#4      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#5      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#6      _Future._completeWithValue (dart:async/future_impl.dart:358)
#7      _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:412)
#8      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#9      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#10     _handleMutation (dart:html:41819)

person Jan Vladimir Mostert    schedule 22.02.2015    source источник


Ответы (1)


Я думаю, вам нужно вызвать функцию JavaScript, например

callback.apply([response]);

Вы не сможете пройти Response таким образом. Вы можете передавать только примитивные значения или наборы примитивных значений, например:

Map arg = {'message': response.message, 'otherfield': response.otherField};
callback.apply([new JsObject.jsify(arg)]);
person Günter Zöchbauer    schedule 22.02.2015
comment
Это успешно выполняет обратный вызов, единственная проблема заключается в том, что ответ при печати представляет собой DartObject {}, а response.message явно не определен - как мне преобразовать этот DartObject в объект JavaScript? - person Jan Vladimir Mostert; 22.02.2015
comment
В этом случае это так же просто, как callback.apply([new JsObject.jsify(response.toJson())]); который преобразует его в карту. response.toJson использует dart:convert для сериализации в Json и обратно. Работает на 100%, спасибо Гюнтер!! - person Jan Vladimir Mostert; 22.02.2015
comment
Да, я не мог знать из предоставленной информации, но я ожидал, что вы сами разберетесь во всем остальном :-). - person Günter Zöchbauer; 22.02.2015