Meteor 方法调用 returns 在客户端未定义但在服务器上未定义

Meteor method call returns undefined on the client but not on the server

更新

我刚刚意识到这种方法存在根本性的错误,嵌套回调不能 return 对其父回调有影响。我进入 JS 世界的时间较晚,来自 Promises 时代,不知道这是回调的问题。但是我没有看到足够多的 Meteor 使用 promises 的例子,所以我改用回调。但是,如果可以改进此代码,我将不胜感激。

问题

所以我使用以下方法从客户端调用一个方法:

Meteor.call('cart.useProfileAddress', {}, (error, address) => {
  console.info('Address', address) // this returns undefined on client
})

这是我api/carts/cartsMethod.js

中的方法
export const useProfileAddress = new ValidatedMethod({
  name: 'cart.useProfileAddress',
  validate(args) {
    //
  },
  run(args) {
    const person = Persons.findOne({'userId': Meteor.userId()});
    // If I do the return here I get the address in the browser as defined.
    // return person.address

    // I'm calling another method under here:
    getClosestStore.call({address: person.address}, (error, result) => {
      // And another one method call here:
      updateCartAddress.call({address: person.address}, (error, result) => {
        // So once all the callbacks are done return the address here.
        // However the problem is I get `undefined` on the client.
        if (!error) {
          // console displays something on the Server but is `undefined` on the Client
          console.info('Returning Address', person.address)
          return person.address
        }
      })
    })
  }
})

上面的代码可能有什么问题?会不会是因为我试图从嵌套回调中获取值?

还有谁知道如何避免这些嵌套回调?我知道如何使用 promises 在 Node 上做到这一点,但在 Meteor 中(我正在使用 1.4)我仍然一无所知。

方法可以 运行 在服务器上同步,因此您不需要使用回调。方法执行后会返回结果,如果出错会抛出异常。试试这个:

export const useProfileAddress = new ValidatedMethod({
  // ...
  run(args) {
    const person = Persons.findOne({'userId': Meteor.userId()});

    const result1 = getClosestStore.call({address: person.address});

    // use result1 if you need to

    const result2 = updateCartAddress.call({address: person.address});

    // // use result2 if you need to

    return person.address;
  }
})

这就是我使用 Promise 和 Meteor 的新 async/await 功能解决问题的方法 1.3+

export const useProfileAddress = new ValidatedMethod({
  name: 'cart.useProfileAddress',
  validate(args) {
    //
  },
  run(args) {
    return ((async () => {
      const person = Persons.findOne({'userId': Meteor.userId()});
      const storeId = await getClosestStore.callPromise({address: person.address})
      const newAddress = await updateCartAddress.callPromise({address: person.address})

      return newAddress
    })())
  }
})

在每个方法中我都使用了 didericis:callpromise-mixin 这样它就会 return 一个 promise。