Flutter - 等待 JavaScript Promise (promiseToFuture)

问题描述

我正在尝试为我的 Flutter 应用程序集成 Braintree 付款。我有一个用于处理 iOS/Android 的插件,并且正在为 Web 编写自定义实现。

我认为这是一个相当简单的解决方案,我使用 Braintree Javascript SDK/Drop in UI (GitHub tutorial) 来使用 HTML 呈现付款屏幕。这部分我开始工作了,但是为了正确处理这些付款,我需要检索 JavaScript 函数的响应 - 特别是付款随机数的字符串。

为此,我使用了一些通道方法和飞镖魔法来调用这个 javascript 函数

async function payment(auth) {
 braintree.dropin.create({
   authorization: auth,selector: '#dropin-container'
 },function (errCreate,instance) {
    document.getElementById("submit-button").addEventListener('click',function () {
        if(errCreate) {
            console.log("Error",errCreate);
            return;
        }
        instance.requestPaymentMethod(function (requestPaymentMethodErr,payload) {
            if (requestPaymentMethodErr) {
                console.log('Error',requestPaymentMethodErr);
                return;
            }
            return payload.nonce;
        });
    });
});
}

这个函数似乎在工作,返回数据和支付随机数等等。在我实际渲染小部件的(单独的)dart 文件中,我像这样声明了函数

// EXTERNAL JAVASCRIPT ==========================================

@JS()
external void initBraintree(auth);

@JS()
external payment(String auth);

这似乎有效,它在按钮单击时调用函数,所以很好。问题是,当我调用这个异步函数时,它返回一个承诺,理论上 dart 不应该知道如何处理这个问题,但幸运的是,他们有一个名为 promisetoFuture 的方法可以处理这个问题。我是这样用的:

  Future<BraintreeDropInResult> start(BuildContext context,BraintreeDropInRequest request) async {
    // create div with html embedded
    String htmlL = """<div id="checkout-message"></div>
        <div id="dropin-container"></div>
    <button id="submit-button">Submit payment</button>""";
    var paymentDiv = html.divelement()..appendHtml(htmlL);

    // attach to payment container
    ui.platformViewRegistry.registerViewFactory('braintree-container',(int viewId) => paymentDiv);

    // call js function
    var promise = payment(request.clientToken);
    String nonce = await promisetoFuture(promise);
 ...

但是它只是不起作用。 JavaScript 函数似乎正在返回一个 promise 对象,但是 promisetoFuture 函数从不等待它,每次都立即返回 null。

已经为此工作了一段时间,终于感觉非常接近,但这对我来说是一个真正的刺,所以非常感谢任何帮助!

解决方法

你可以做这样的事情。即创建一个承诺,一旦一切正常——点击按钮——它将用随机数解决。

当然,这仅适用于第一次点击按钮。因为,一旦承诺被解决或拒绝,它就不会再改变它的状态和结果。

async function payment(auth) {
  return new Promise((resolve,reject) => {
    braintree.dropin.create({
        authorization: auth,selector: '#dropin-container'
      },(createError,instance) => {
        //probably there is no need to attach the eventhandler
        //if the was an error 
        if (createError) {
          console.log("Error",createError);
          return reject(createError);
        }
        document.getElementById("submit-button").addEventListener("click",() => {
            instance.requestPaymentMethod((rpmError,payload) => {
              if (rpmError) {
                console.log("Error",rpmError);
                return reject(rpmError);
              }
 
              resolve(payload.nonce);
            });
          });
      }
    );
  });
}