I'm using Meteor, what do I need to do to wait for a promise to be returned from an API call?

江枫思渺然 提交于 2019-11-28 11:13:40

问题


if (Meteor.isClient) {

  Template.hello.events({
    'click input': function () {

      //create a new customer
      Meteor.call('createCustomer', function (error, result) { 
        console.log("Error: " + error + "  Result: " + result); } );
    }
  });
}

if (Meteor.isServer) {
  Meteor.methods({
    createCustomer: function () {
      try {
      balanced.configure('MyBalancedPaymentsTestKey');
      var customer = Meteor._wrapAsync(balanced.marketplace.customers.create());
      var callCustomer = customer();
      var returnThis = console.log(JSON.stringify(callCustomer, false, 4));
      return returnThis;
    } catch (e) {
      console.log(e);
      var caughtFault = JSON.stringify(e, false, 4);
    }
    return caughtFault;
    }
  });
}

And I just used the default hello world without the greetings line.

<head>
  <title>testCase</title>
</head>

<body>
  {{> hello}}
</body>

<template name="hello">
  <h1>Hello World!</h1>
  <input type="button" value="Click" />
</template>

On the client side the log prints

Error: undefined Result: {}

On the server side the log prints

[TypeError: Object [object Promise] has no method 'apply']

Any idea how I can wait for that promise instead of returning the blank result?


回答1:


I'm assuming balanced.marketplace.customers.create returns a Promises/A+ promise. This is an object with a method .then(fulfillmentCallback, rejectionCallback) - the fulfillmentCallback is called when the operation succeeds, and the rejectionCallback is called if the operation had an error. Here's how you could use Futures to synchronously get the value out of a promise:

var Future = Npm.require("fibers/future");

function extractFromPromise(promise) {
  var fut = new Future();
  promise.then(function (result) {
    fut["return"](result);
  }, function (error) {
    fut["throw"](error);
  });
  return fut.wait();
}

Then you can just call balanced.marketplace.customers.create normally (no _wrapAsync) to get a promise, then call extractFromPromise on that promise to get the actual result value. If there's an error, then extractFromPromise will throw an exception.

By the way, code in if (Meteor.isServer) blocks is still sent to the client (even if the client doesn't run it), so you don't want to put your API key in there. You can put code in the server directory, and then Meteor won't send it to the client at all.




回答2:


Update this line

 var customer = Meteor._wrapAsync(balanced.marketplace.customer.create)();



回答3:


Another approach is to use Futures. I use this a lot on the server side to wait for results to return back to the client.

Here's a small example of that I use for logins:

Accounts.login(function (req, user) {
    var Future = Npm.require("fibers/future");
    var fut = new Future();
    HTTP.call("POST", globals.server + 'api/meteor-approvals/token',
        {
            timeout: 10000, followRedirects: true,
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            params: {
                username: userName,
                password: req.password
            }},
        function (err, result) {
            if (err) {
                logger.error("Login error: " + err);
                fut.throw(err);
            }
            else {
                fut.return("Success");
            }
        }
    );
    return fut.wait();
}


来源:https://stackoverflow.com/questions/23773057/im-using-meteor-what-do-i-need-to-do-to-wait-for-a-promise-to-be-returned-from

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!