Meteor 客户端在服务器方法中调用 findOne

Posted

技术标签:

【中文标题】Meteor 客户端在服务器方法中调用 findOne【英文标题】:Meteor Client calling findOne in Server Method 【发布时间】:2022-01-07 13:07:20 【问题描述】:

我有一个客户端表单,可以在提交时创建一个文档。我想查看其中一个输入字段是否已经存在于数据库中的 Document 上。然后这会提醒用户并询问他们是否要继续创建记录。

客户端事件

Template.createDoc.events(
    'click button[type=submit]'(e, template) 

        //This particular example is checking to see if a Doc with its `name` property set to `value` already exists

        const value = $('#name');
        const fieldName = 'name';

        const exists = Meteor.call('checkIfFieldExistsOnDoc', fieldName, value);
        if (exists) 
            if (confirm(`Doc with $value as its $fieldName already exists. Are you sure you want to continue creating Doc?`) 
               //db.Docs.insert....
           
        
    
);

服务器端 Meteor 方法

'checkIfFieldExistsOnDoc'(field, val) 
    
    if (this.isServer) 
      this.unblock();
      check(field, String);
      check(val, String);

      if (!this.userId) 
        throw new Meteor.Error('not-authorized', 'You are not authorized.');
      

      const findObj = ;
      findObj[field] = val;

      const fieldsObj = ;
      fieldsObj[fieldsObj] = 1;

      const doc = Docs.findOne(findObj, fields: fieldsObj);
      return doc;
    
  ,

我的问题是客户端代码在调用 Server 方法时总是未定义。但是,我现在明白了为什么我还不热衷于将所有后续客户端代码包装到回调中。

那么 - 关于如何尝试实现这个简单功能的任何其他想法?

另外 - 我正在考虑让客户端页面的 onCreated 执行 1 次服务器调用以获取所有 names 的所有 Docs,将其存储在内存中,然后在提交表单时进行检查使用这个。显然,这是低效且不可扩展的,尽管它可以工作

【问题讨论】:

【参考方案1】:

客户端的 Meteor.call 始终是异步调用。然后你需要实现一个回调。

请参阅文档:https://docs.meteor.com/api/methods.html#Meteor-call

Meteor.call('checkIfFieldExistsOnDoc', fieldName, value, function(error, result) 
  if (result) 
    if (confirm(`Doc with $value as its $fieldName already exists. Are you sure you want to continue creating Doc?`) 
      //db.Docs.insert....
    
  
);

【讨论】:

谢谢,我希望有一些方法可以避免 cb 语法。我知道删除服务器上的参数会添加一些语法糖,使其“同步”有点像 await.. 所以 - 只是想知道在客户端是否也有办法做到这一点 @user2402616,尝试 async/await,但请记住,如果前端有一些异步调用来呈现您的页面,您将失去一个很大的优势。【参考方案2】:

在客户端,您可以使用 Promise 包装任何 Meteor.call,然后将其与 async/await 一起使用。 Atmosphere 上有一些软件包可以为您执行此操作。

我已经使用这个包多年了:https://atmospherejs.com/deanius/promise

在客户端上,我经常只使用await Meteor.callPromise(),它会很好地返回响应。

以下是一些关于您可用的许多选项的最佳文章:

    https://blog.meteor.com/using-promises-on-the-client-in-meteor-fb4f1c155f84 https://forums.meteor.com/t/meteor-methods-return-values-via-promise-async/42060 https://dev.to/jankapunkt/async-meteor-method-calls-24f9

【讨论】:

在客户端代码调用异步到服务器的情况下,有这样的模式是否被认为是“坏”的做法?我认为不是哈哈,因为这是 JS 的好处之一。我之所以质疑它只是因为我意识到这真的是我第一次在 Meteor 中这样做 Meteor 的很多特性都是在 async/await 添加到 JS 之前设计的,这就是为什么以前从客户端进行 async/await 调用不太常见,但现在很常见在流星社区。 Meteor 的一大优点是客户端和服务器之间的开放式 DDP 连接,因此异步/等待调用在该开放式连接上非常快。

以上是关于Meteor 客户端在服务器方法中调用 findOne的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Meteor 中使用客户端重新连接事件

在 Apollo Mutation 中调用 Meteor 方法

Meteor 同步方法调用

如何使 Meteor 方法同步?

如何从Meteor.js中的方法内部的方法返回错误

正确使用 Meteor.userId()