配置并打开同步 Realm - Node.js SDK
同步 Realm
您可以配置 Realm,以在许多设备之间自动同步数据,并且每个设备都有自己的本地数据副本。同步 Realm 使用与纯本地 Realm 不同的配置,并且需要 Atlas App Services 后端处理同步过程。
应用程序始终可以在本地创建、修改和删除同步的域对象,即使在离线状态下也是如此。 只要网络连接可用, Realm 软件开发工具包(Realm SDK)就会建立与应用程序服务器的连接,并与其他客户端进行双向更改同步。 Atlas Device Sync协议和服务器端操作转换可确保域的所有完全同步实例看到完全相同的数据,即使某些更改发生在离线状态和/或接收时无序。
先决条件
在 Node.js 应用程序中使用 Flexible Sync 配置域之前:
在后端启用 Flexible Sync。您必须在后端配置 Flexible Sync,然后才能在客户端应用程序中使用。
对客户端项目中的用户进行身份验证。
打开同步 Realm
实施 Device Sync 的第一步是打开同步的 Realm。 以下信息适用于使用 Flexible Sync 的应用。 如果您的现有应用程序使用较旧的基于分区的同步,请参阅打开基于分区的同步 Realm 。 如果您尚未决定或不确定使用哪一种,请阅读“选择同步模式”页面。
要使用 Flexible Sync 打开域 ,请调用Realm.open() 。 传入ConfigurationWithSync对象,该对象必须包含定义SyncConfiguration对象的 sync
属性。 在 SyncConfiguration 中,您必须包含user
和flexible:true
。
const realm = await Realm.open({ schema: [TaskSchema, TeamSchema], sync: { user: app.currentUser, flexible: true, }, });
默认, Realm在返回之前会同步服务器的所有数据。 如果您想在背景同步数据,请阅读“离线时打开同步Realm ”部分。
打开特定路径上的同步 Realm
realm@11.6.0
版本中的新增功能。
使用AppConfiguration.baseFilePath和Realm.Configuration.path 、 您可以控制Realm和元数据文件在客户端设备上的存储位置。
为此,请设置<AppProvider>.baseFilePath
。如果未设置baseFilePath
,则使用当前工作目录。您还可以设置<RealmProvider>.sync.path
以进行更多控制。
const app = new Realm.App({ id: APP_ID, baseFilePath: customPath }); const user = await app.logIn(Realm.Credentials.anonymous()); const realm = await Realm.open({ schema: [Car], sync: { flexible: true, user, }, });
如果设置了baseFilePath
,则元数据始终存储在<baseFilePath>/mongodb-realm/
中。 如果未设置baseFilePath
,则元数据存储在<Realm.defaultPath>/mongodb-realm
中。
Realm 文件的确切存储位置可能会有所不同,具体取决于您设置Realm.Configuration.path 的方式:
Realm.Configuration.path
未设置,baseFilePath
已设置。您的 Realm 文件存储在baseFilePath
。Realm.Configuation.path
设置为相对路径。您的 Realm 文件的存储路径是相对于baseFilePath
而言的。Realm.Configuration.path
是绝对路径。您的 Realm 文件存储在Realm.Configuration.path
中。
离线时打开同步 Realm
当您的 Realm 应用程序对用户进行身份验证时,它会缓存该用户的档案。您可以检查是否存在现有用户档案以绕过登录流程并访问已缓存的用户。使用它可离线打开一个 Realm。
注意
初始登录需要网络连接
当用户注册您的应用或使用客户端上的现有帐户首次登录时,客户端必须具有网络连接。通过检查是否存在已缓存的用户档案,您可以离线打开 Realm,但前提是用户之前已在线登录。
// Log user into your App Services App. // On first login, the user must have a network connection. const getUser = async () => { // If the device has no cached user credentials, log in. if (!app.currentUser) { const credentials = Realm.Credentials.anonymous(); await app.logIn(credentials); } // If the app is offline, but credentials are // cached, return existing user. return app.currentUser!; };
以下各小节介绍如何使用后台同步在离线状态下访问 Realm。 为此,请使用缓存的用户和OpenRealmBehaviorConfiguration对象。
在同步配置中,将可选的newRealmFileBehavior
和existingRealmFileBehavior
字段设置为OpenRealmBehaviorConfiguration
对象,以启用背景同步。
重要
灵活同步配置和基于分区的同步配置均支持离线登录
您可以使用后台同步立即打开 Realm,也可以使用“Flexible Sync”或较旧的“基于分区的同步”在超时后打开 Realm。
基于分区的同步是一种过时的同步模式。 有关在应用程序中使用基于分区的同步的详细信息,请参阅基于分区的同步 - Node.js SDK页面。
使用背景同步立即打开
如果用户的设备未连接到互联网,或者您不确定设备的连接状态,请将 Realm 行为的类型设置为openImmediately
。 这会在后台同步来自服务器的数据。
const behaviorConfiguration = { type: "openImmediately", }; const config = { schema: [Car], sync: { user: await getUser(), flexible: true, newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config);
const behaviorConfiguration: Realm.OpenRealmBehaviorConfiguration = { type: "openImmediately", }; const config: Realm.Configuration = { schema: [Car], sync: { user: await getUser(), flexible: true, newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config);
使用背景同步在超时后打开
如果您想要同步数据,但所处环境不确定用户是否有 Internet 连接,请指定timeOut
。 当出现以下任一情况时,此功能会自动打开 Realm:
超时时间已过。
Realm 已完全下载。
如果 Realm 在超时前未完成下载,则初始 Realm 同步会在后台继续。
const behaviorConfiguration = { type: "openImmediately", timeOut: 1000, timeOutBehavior: "openLocalRealm", }; const config = { schema: [Car], sync: { flexible: true, user: await getUser(), existingRealmFileBehavior: behaviorConfiguration, newRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config);
const behaviorConfiguration: Realm.OpenRealmBehaviorConfiguration = { type: "openImmediately", timeOut: 1000, timeOutBehavior: "openLocalRealm", }; const config: Realm.Configuration = { schema: [Car], sync: { flexible: true, user: await getUser(), existingRealmFileBehavior: behaviorConfiguration, newRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config);
在背景同步更改
您可能希望在后台同步变更,以便在同步 Realm 从服务器下载数据时向用户显示部分数据,防止用户体验受限。对于用户设备可能离线的应用程序,我们建议在后台同步变更。要在后台同步变更,请同步打开同步 Realm。
创建一个OpenRealmBehaviorConfiguration对象设立其type
设置为"openImmediately"
。
const behaviorConfiguration = { type: "openImmediately", };
const behaviorConfiguration: Realm.OpenRealmBehaviorConfiguration = { type: Realm.OpenRealmBehaviorType.OpenImmediately, };
创建一个配置对象,该对象必须包含定义SyncConfiguration对象的sync
属性。 将此OpenRealmBehaviorConfiguration
对象设置为SyncConfiguration
的newRealmFileBehavior
和existingRealmFileBehavior
字段的值。
const config = { schema: [DogSchema], sync: { user: app.currentUser, partitionValue: "MyPartitionValue", // The behavior to use when this is the first time opening a realm. newRealmFileBehavior: behaviorConfiguration, // The behavior to use when a realm file already exists locally, // i.e. you have previously opened the realm. existingRealmFileBehavior: behaviorConfiguration, }, };
const config: Realm.Configuration = { schema: [DogSchema], sync: { user: app.currentUser!, partitionValue: "MyPartitionValue", // The behavior to use when this is the first time opening a realm. newRealmFileBehavior: behaviorConfiguration, // The behavior to use when a realm file already exists locally, // i.e. you have previously opened the realm. existingRealmFileBehavior: behaviorConfiguration, }, };
最后,调用Realm.open()打开同步域。 这将创建一个同步会话,并开始在背景从服务器下载任何现有数据。
const realm = await Realm.open(config);
超时后取消异步操作
版本 12.0.0 中的新增内容。
您可以在BaseSyncConfiguration对象中指定cancelWaitsOnNonFatalErrors
属性。
设为true
时, Node.js SDK会在超时时间过后取消异步操作,例如等待上传或下载。 您可以在AppConfiguration上为此选项定义超时。 有关示例,请参阅为 App Client 配置超时。
如果未指定值,则此属性默认为false
。
const config = { schema: [Doggie], sync: { flexible: true, user: app.currentUser, // When `true`, upload and download waits are canceled on any // error, such as a timeout, instead of just a fatal error. // You can provide an optional timeouts property in milliseconds. cancelWaitsOnNonFatalError: true, }, };
const config: Realm.Configuration = { schema: [Doggie], sync: { flexible: true, user: app.currentUser!, // When `true`, upload and download waits are canceled on any // error, such as a timeout, instead of just a fatal error. // You can provide an optional timeouts property in milliseconds. cancelWaitsOnNonFatalError: true, }, };