【问题标题】:Meteor method call returns undefined on the client but not on the serverMeteor 方法调用在客户端返回 undefined 但在服务器上没有
【发布时间】:2017-06-25 14:36:47
【问题描述】:

更新

我刚刚意识到这种方法存在根本性的错误,嵌套回调无法将某些内容返回到其父回调。我在 JS 世界中来得很晚,来自Promises 时代,不知道这是回调的问题。但是我没有看到足够的 Meteor 使用 Promise 的例子,所以我使用了回调。但是,如果可以改进此代码,我将不胜感激。

问题

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

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

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

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

【问题讨论】:

    标签: javascript meteor meteor-accounts


    【解决方案1】:

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

    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,以便它返回一个承诺。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 非常感谢!我假设如果您从方法调用中删除回调,使其同步,对吗?如果是这样,如果代码现在变得阻塞,客户端是否会受到这种方法的影响?
      • 当然,客户端只有在两个方法完成后才收到结果
      • 我遇到了这种方法的问题。 getClosestStore.call 总是做异步,因为它是另一个异步调用的包装器,它从另一个 api 获取距离。是否可以在方法内传递回调,以便我可以在最里面的回调中调用?如果一切都失败了,我将使用承诺。
      • 你不能这样做,因为函数不能序列化,我认为你可以在getClosestStore方法中使用promise
      • 我实际上尝试过放置回调函数,你是对的,感谢您为我指出解决方案!
      猜你喜欢
      • 1970-01-01
      • 2016-07-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 2016-05-16
      相关资源
      最近更新 更多