Meteor方法在客户端返回undefined,但在服务器端不是

4

更新

我刚意识到这种方法存在根本性问题,嵌套回调函数无法将结果返回给其父回调函数。我是在JavaScript世界中很晚才了解了这一点,来自于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
        }
      })
    })
  }
})

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

还有,有人知道如何避免这些嵌套回调吗?我知道如何在Node中使用promises来解决,但在Meteor(我正在使用1.4)中仍然一筹莫展。

2个回答

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;
  }
})

非常感谢!我假设如果您从方法调用中删除回调,那么它就变成同步的了,这是正确的吗?如果是这样,如果代码现在变成阻塞的,客户端会受到影响吗? - JohnnyQ
当然,在这两个方法完成后,客户端才会收到结果。 - kkkkkkk
我对这种方法有问题。getClosestStore.call总是异步的,因为它是另一个从另一个API获取距离的异步调用的包装器。是否可以在方法内部传递回调函数,以便我可以在最内层的回调中调用它?如果一切都失败了,我将使用promises。 - JohnnyQ
1
你不能这样做,因为函数无法序列化,我认为你可以在 getClosestStore 方法中使用 Promise。 - kkkkkkk
我实际上尝试了将回调函数放置在那里,你是对的,感谢指引我找到解决方案! - JohnnyQ

3
这是我使用 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,以便它返回一个Promise。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接