You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Meteor调用createUser触发EJSON.clone循环引用错误求助

解决Accounts.createUser引发的EJSON.clone循环调用错误

嘿,我帮你梳理下这个问题——你遇到的EJSON.clone循环调用错误,大概率和代码里的几个不合理操作以及Meteor用户对象的规范有关,咱们一步步来解决:

1. 先删掉多余的手动登录逻辑

首先要明确:Meteor的Accounts.createUser在成功创建用户后,会自动帮你完成登录,完全不需要再手动调用Meteor.loginWithPassword。这一步多余的调用不仅没必要,还可能触发内部状态的冲突,间接导致EJSON序列化时出问题。

把这段冗余代码删掉:

// 删掉这段多余的登录逻辑
Meteor.loginWithPassword(email, password, function(err) {
    if (err) {
        console.log("Error logging in");
        console.log(err);
        Materialize.Toast.removeAll();
        Materialize.toast("There was an error logging you in. Try logging in manually. If this error persists, contact support.", 8000);
    } else {
        console.log("Logged in!");
        FlowRouter.go('/');
    }
})

改成直接在createUser成功回调里跳转:

Accounts.createUser(accountInfo, function(err) {
    if (err) {
        // ...你的错误处理逻辑
    } else {
        console.log("用户创建成功,已自动登录!");
        FlowRouter.go('/');
    }
});

2. 修复变量未定义的坑

顺便提一句,你原来的Meteor.loginWithPassword(email, password)里的emailpassword是未定义的变量——你应该用accountInfo.emailaccountInfo.password。不过既然我们已经删掉了这段代码,这个问题也就顺带解决了。

3. 调整服务端用户对象的结构,符合Meteor规范

你在服务端onCreateUser里直接把options.email赋值给user.email,但Meteor默认的用户结构中,邮箱是存在user.emails数组里的(每个元素包含addressverified字段)。额外添加的user.email字段可能干扰Meteor内部的序列化逻辑,这很可能是EJSON循环调用的根源。

修改服务端代码,遵循Meteor的默认结构:

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';

Accounts.onCreateUser((options, user) => {
    // 保留默认的profile处理逻辑
    if (options.profile) {
        user.profile = options.profile;
    }
    // 自定义字段直接作为user的顶层字段没问题
    user.first_name = options.first_name;
    user.last_name = options.last_name;
    user.phone_number = options.phone_number;
    
    // 邮箱交给Meteor自动处理即可,createUser会自动把options.email加入user.emails数组
    return user;
});

4. 排查EJSON循环引用的其他可能

如果上面的调整后还是有问题,那你需要检查:

  • accountInfo里的每个字段是不是都是基本类型(字符串、数字),有没有不小心传入了对象/数组或者存在循环引用的值;
  • 有没有第三方库(比如Materialize相关的代码)修改了全局对象,影响了EJSON的序列化逻辑;
  • 尝试把Meteor的accounts-baseejson包更新到最新版本,可能是旧版本的bug导致的。

5. 暂时移除sleep延迟测试

虽然sleep函数本身不会导致循环引用,但建议先把它去掉,排除异步延迟带来的状态问题,先确保createUser的基础调用能正常工作。

调整后的客户端代码示例

onSubmit(e) {
    let input_valid = this.validateInput();
    if (!input_valid) {
        Materialize.updateTextFields();
        e.preventDefault();
        return;
    }

    Materialize.Toast.removeAll();
    let $toastContent = $('<div class="container" style="width: 200px"><div class="row">Creating account...</div><div class="row"><div class="progress"><div class="indeterminate"></div></div></div></div>');
    Materialize.toast($toastContent, 10000);

    let accountInfo = {
        first_name: this.state.first_name.value,
        last_name: this.state.last_name.value,
        email: this.state.email.value,
        password: this.state.password.value,
        phone_number: this.state.phone_number.value,
    };

    Accounts.createUser(accountInfo, (err) => {
        Materialize.Toast.removeAll();
        if (err) {
            console.error("创建用户出错:", err);
            Materialize.toast("创建账户时出错,请稍后重试。如果问题持续,请联系支持人员。", 8000);
        } else {
            console.log("用户创建成功!");
            FlowRouter.go('/');
        }
    });

    e.preventDefault();
}

按照上面的步骤逐一调整,应该就能解决你遇到的EJSON循环调用错误了。

内容的提问来源于stack exchange,提问作者TheWaffleDimension

火山引擎 最新活动