wrapAsync返回函数不是结果

时间:2018-03-30 09:38:21

标签: javascript meteor ecmascript-6

好吧,诺布在这里。还在学习。我不明白我如何让我的方法将我的Meteor.wrapAsync函数的结果返回给客户端上的Meteor.call。我的方法中的console.log(companies);生成一个函数,而不是结果。我在这里不理解什么?

路径:client.jsx

Meteor.call('getTop100ASX', (error, result) => {
  console.log(result);
});

路径:method.js

Meteor.methods({
  'getTop100ASX'() {
    const aggregateFunc = db.collection('companiesASX').aggregate([{
      $group: {
        _id: {
          location: "$google_maps.geometry_location"
        },
        companies: {
          $addToSet: {
            name: "$company_name"
          }
        }
      }
    }]).toArray((err, result) => {
      return result;
    });

    const companies = Meteor.wrapAsync(aggregateFunc);

    console.log(companies);

    return companies;
  },
});

1 个答案:

答案 0 :(得分:2)

wrapAsync包装一个通常需要回调的函数,并且可以使用fibers以同步方式在服务器上调用该包装函数(即,接受函数+上下文并返回一个功能)。

它无法获取某些价值并从中神奇地提取预期结果(例如,在您的示例中,result回调中的toArray

你给它的不是一个函数,而是一个Promise对象(从调用toArray返回的)。

由于它已经返回一个承诺,你有几个选择:

更简单的是返回该promise(并且不需要toArray()中的回调),因为如果Meteor方法返回一个promise,服务器将等待promise解析然后返回结果给客户。

Meteor.methods({
  'getTop100ASX'() {
    return db.collection('companiesASX').aggregate([...]).toArray();
  },
});

如果您需要在方法中进一步处理companies,可以使用async / await,例如:

Meteor.methods({
  async 'getTop100ASX'() {
    const companies = await db.collection('companiesASX').aggregate([{
      $group: {
        _id: {
          location: "$google_maps.geometry_location"
        },
        companies: {
          $addToSet: {
            name: "$company_name"
          }
        }
      }
    }]).toArray();

    let someResult = sumeFunc(companies);

    return someResult;
  },
});

为了完整性,为了使用wrapAsync,您应该提供toArray方法和上下文,如下所示:

Meteor.methods({
  'getTop100ASX'() {
    const cursor = db.collection('companiesASX').aggregate([{
      $group: {
        _id: {
          location: "$google_maps.geometry_location"
        },
        companies: {
          $addToSet: {
            name: "$company_name"
          }
        }
      }
    }]);

    // wrap the cursor's `toArray` method and preservs the context
    const syncToArray = Meteor.wrapAsync(cursor.toArray, cursor);

    // and call the wrapped function in a sync manner
    const companies = syncToArray();

    return companies;
  },
});