【问题标题】:Calling a Meteor Method inside a Promise Callback [Halting w/o Error]在 Promise 回调中调用 Meteor 方法 [Halting w/o Error]
【发布时间】:2016-03-26 10:37:38
【问题描述】:

我正在尝试在我的 Meteor 应用程序中使用这个 NPM 包:Gumroad-API。当我尝试在 Promise 回调中执行 Meteor 方法调用(或集合插入)时,我在服务器端遇到了问题。

以下是我的两个 Meteor 方法的代码:

Meteor.methods({

  testMethod: () => {
    console.log('TEST METHOD RUN');
  },

  fetchGumroadData: () => {
    const Gumroad = Meteor.npmRequire('gumroad-api');
    let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });

    Meteor.call('testMethod');        // runs fine

    gumroad.listSales('2014-12-04', '2099-12-04', 1).then((result) => {
      console.log('1');               // runs fine
      Meteor.call('testMethod');      // execution halts here w/o error msg
      console.log('2');               // this never runs
    });
  },
});

每当我尝试在其中执行 Meteor.call() 时,.then() 回调中的代码总是停止(没有错误消息)。

当我将 Meteor.call() 替换为 Collection.insert() 时,我得到了相同的行为,例如:Sales.insert({text:'test'});

【问题讨论】:

    标签: javascript node.js meteor npm promise


    【解决方案1】:

    我很少使用 Promise,所以我不知道您为什么会看到该错误。当使用像这样的外部 API 时,我通常使用 wrapAsync,因此我可以以同步方式编写代码,但仍能获得相同的结果。

    在你的情况下,看起来像这样:

    Meteor.methods({
    
      testMethod: () => {
        console.log('TEST METHOD RUN');
      },
    
      fetchGumroadData: () => {
        const Gumroad = Meteor.npmRequire('gumroad-api');
        let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });
    
        Meteor.call('testMethod');        // runs fine
    
        let wrappedListSales = Meteor.wrapAsync(gumroad.listSales, gumroad);
    
        let result = wrappedListSales('2014-12-04', '2099-12-04', 1);
    
        console.log('1');               
        Meteor.call('testMethod');      
        console.log('2');               
      },
    });
    

    Meteor.wrapAsync 的第二个参数是可选的,可能不需要,这取决于 gumroad API 的性质

    【讨论】:

    • 不幸的是,这并没有解决我的问题。它现在停在let result = ... 行。我在想也许我根本不会使用这个 NPM 包,我会自己发出 API 请求。
    【解决方案2】:

    我最终放弃了 NPM 包并编写了自己的 API 调用。我永远无法弄清楚如何在.then() 内拨打电话。代码如下:

    fetchGumroadData: () => {
      let options = {
        data: {
          access_token: Meteor.settings.gumroadAccessKey,
          before: '2099-12-04',
          after: '2014-12-04',
          page: 1,
        }
      };
      HTTP.call('GET', 'https://api.gumroad.com/v2/sales', options, (err,res) => {
        if (err) {  // API call failed
          console.log(err);
          throw err;
        } else {    // API call successful
          Meteor.call('testMethod');
        }
      });
    }
    

    【讨论】:

      【解决方案3】:

      老问题,但是失败的原因是因为 Meteor 环境在您的回调中不可用。

      请注意这是未经测试的代码

      Meteor.methods({
      
        testMethod: () => {
          console.log('TEST METHOD RUN');
        },
      
        fetchGumroadData: () => {
          const Gumroad = Meteor.npmRequire('gumroad-api');
          let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });
      
          Meteor.call('testMethod');        // runs fine
      
          gumroad.listSales('2014-12-04', '2099-12-04', 1)
            .then(Meteor.bindEnvironment((result) => {
              console.log('1');               // runs fine
              Meteor.call('testMethod');      // execution halts here w/o error msg
              console.log('2');               // this never runs
            }));
          },
      });
      

      关于 bindEnvironment 和 wrapAsync 的教程可以在这里找到:https://www.eventedmind.com/items/meteor-what-is-meteor-bindenvironment

      【讨论】:

      • 感谢您花时间在一个老问题上发布这个——对我来说真的很有用。我使用的是 bindEnvironment,但包装了错误的函数调用。在上面的示例中,我包装了第二个 Meteor.call。我想添加我收到的错误消息,希望能帮助别人:错误:Meteor 代码必须始终在 Fiber 中运行。尝试使用 Meteor.bindEnvironment 包装传递给非 Meteor 库的回调。
      • 没问题,很高兴它有帮助! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      • 1970-01-01
      • 2019-02-25
      • 2013-04-22
      • 2019-02-08
      • 2016-06-26
      • 1970-01-01
      相关资源
      最近更新 更多