为 Cordova 移动应用启用脱机同步Enable offline sync for your Cordova mobile app


本教程介绍适用于 Cordova 的 Azure 移动应用的脱机同步功能。This tutorial introduces the offline sync feature of Azure Mobile Apps for Cordova. 借助脱机同步,最终用户即使在没有网络连接时也能够与移动应用进行交互(查看、添加或修改数据)。Offline sync allows end users to interact with a mobile app—viewing, adding, or modifying data—even when there is no network connection. 在本地数据库中存储更改。Changes are stored in a local database. 设备重新联机后,这些更改会与远程服务同步。Once the device is back online, these changes are synced with the remote service.

本教程基于完成教程 Apache Cordova 快速入门时创建的移动应用的 Cordova 快速入门解决方案。This tutorial is based on the Cordova quickstart solution for Mobile Apps that you create when you complete the tutorial Apache Cordova quick start. 本教程会更新快速入门解决方案,以添加 Azure 移动应用的脱机功能。In this tutorial, you update the quickstart solution to add offline features of Azure Mobile Apps. 我们还重点介绍了该应用中的特定于脱机的代码。We also highlight the offline-specific code in the app.

若要了解有关脱机同步功能的详细信息,请参阅主题 Azure 移动应用中的脱机数据同步To learn more about the offline sync feature, see the topic Offline Data Sync in Azure Mobile Apps. 若要深入了解 API 用法,请参阅 API 文件For details of API usage, see the API documentation.

在快速入门解决方案中添加脱机同步功能Add offline sync to the quickstart solution

应用中必须添加脱机同步代码。The offline sync code must be added to the app. 脱机同步功能需要 cordova-sqlite-storage 插件,该插件会在项目中包含 Azure 移动应用时自动添加到应用中。Offline sync requires the cordova-sqlite-storage plugin, which automatically gets added to your app when the Azure Mobile Apps plugin is included in the project. 快速入门项目包含上述两个插件。The Quickstart project includes both of these plugins.

  1. 在 Visual Studio 解决方案资源管理器中,打开 index.js,并将以下代码In Visual Studio's Solution Explorer, open index.js and replace the following code

     var client,            // Connection to the Azure Mobile App backend
        todoItemTable;      // Reference to a table endpoint on backend

    替换为此代码:with this code:

     var client,            // Connection to the Azure Mobile App backend
        todoItemTable,      // Reference to a table endpoint on backend
        syncContext;        // Reference to offline data sync context
  2. 接下来,将以下代码:Next, replace the following code:

     client = new WindowsAzure.MobileServiceClient('http://yourmobileapp.chinacloudsites.cn');

    替换为此代码:with this code:

     client = new WindowsAzure.MobileServiceClient('http://yourmobileapp.chinacloudsites.cn');
     var store = new WindowsAzure.MobileServiceSqliteStore('store.db');
       name: 'todoitem',
       columnDefinitions: {
           id: 'string',
           text: 'string',
           complete: 'boolean',
           version: 'string'
     // Get the sync context from the client
     syncContext = client.getSyncContext();

    前面增加的代码会初始化本地存储,并定义与 Azure 后端中使用的列值匹配的本地表。The preceding code additions initialize the local store and define a local table that matches the column values used in your Azure back end. (无需在此代码中包含所有列值。)) version 字段由移动后端维护并用于冲突解决方案。(You don't need to include all column values in this code.) The version field is maintained by the mobile backend and is used for conflict resolution.

    调用 getSyncContext可获取对同步上下文的引用。You get a reference to the sync context by calling getSyncContext. 对于调用 .push() 时客户端应用修改的所有表,此同步上下文通过跟踪和推送这些表中的更改来帮助保持表关系。The sync context helps preserve table relationships by tracking and pushing changes in all tables a client app has modified when .push() is called.

  3. 将应用程序 URL 更新为移动应用的应用程序 URL。Update the application URL to your Mobile App application URL.

  4. 接下来,将此代码:Next, replace this code:

     todoItemTable = client.getTable('todoitem'); // todoitem is the table name

    替换为此代码:with this code:

     // Initialize the sync context with the store
     syncContext.initialize(store).then(function () {
     // Get the local table reference.
     todoItemTable = client.getSyncTable('todoitem');
     syncContext.pushHandler = {
         onConflict: function (pushError) {
             // Handle the conflict.
             console.log("Sync conflict! " + pushError.getError().message);
             // Update failed, revert to server's copy.
           onError: function (pushError) {
               // Handle the error
               // In the simulated offline state, you get "Sync error! Unexpected connection failure."
               console.log("Sync error! " + pushError.getError().message);
     // Call a function to perform the actual sync
     // Refresh the todoItems
     // Wire up the UI Event Handler for the Add Item
     $('#refresh').on('click', refreshDisplay);

    前面的代码会初始化同步上下文,然后调用 getSyncTable(而不是 getTable)来获取对本地表的引用。The preceding code initializes the sync context and then calls getSyncTable (instead of getTable) to get a reference to the local table.

    此代码使用本地数据库进行所有创建、读取、更新和删除 (CRUD) 表操作。This code uses the local database for all create, read, update, and delete (CRUD) table operations.

    此示例会对同步冲突执行简单的错误处理。This sample performs simple error handling on sync conflicts. 实际应用程序会处理各种错误,例如网络状况、服务器冲突等。A real application would handle the various errors like network conditions, server conflicts, and others. 有关代码示例,请参阅 脱机同步示例For code examples, see the offline sync sample.

  5. 接下来,添加此函数以执行实际同步操作。Next, add this function to perform the actual sync.

     function syncBackend() {
       // Sync local store to Azure table when app loads, or when login complete.
       syncContext.push().then(function () {
           // Push completed
       // Pull items from the Azure table after syncing to Azure.
       syncContext.pull(new WindowsAzure.Query('todoitem'));

    调用 syncContext.push() 可决定何时将更改推送到移动应用后端。You decide when to push changes to the Mobile App backend by calling syncContext.push(). 例如,在绑定到同步按钮的按钮事件处理程序中,可调用 syncBackendFor example, you could call syncBackend in a button event handler tied to a sync button.

脱机同步注意事项Offline sync considerations

示例中 syncContext 的 push 方法仅会在应用启动时在登录的回调函数中调用。In the sample, the push method of syncContext is only called on app startup in the callback function for login. 在实际应用程序中,还可以手动或在网络状态发生更改时触发此同步功能。In a real-world application, you could also make this sync functionality triggered manually or when the network state changes.

如果对一个表执行拉取操作,并且该表具有由上下文跟踪的未完成的本地更新,那么该拉取操作自动触发推送操作。When a pull is executed against a table that has pending local updates tracked by the context, that pull operation automatically triggers a push. 在此示例中刷新、添加和完成项时,可省略显式 push 调用,因为它可能是冗余的。When refreshing, adding, and completing items in this sample, you can omit the explicit push call, since it may be redundant.

在所提供的代码中,会查询远程 todoItem 表中的所有记录,也可以筛选记录,只需将查询 ID 和查询传递给 push 即可。In the provided code, all records in the remote todoItem table are queried, but it is also possible to filter records by passing a query id and query to push. 有关详细信息,请参阅 Azure 移动应用中的脱机数据同步 中的 增量同步部分。For more information, see the section Incremental Sync in Offline Data Sync in Azure Mobile Apps.

(可选)禁用身份验证(Optional) Disable authentication

如果不想在测试脱机同步功能之前设置身份验证,请注释禁止登录的回调函数,但让回调函数内部的代码保持取消注释状态。If you don't want to set up authentication before testing offline sync, comment out the callback function for login, but leave the code inside the callback function uncommented. 注释禁止登录行后,该代码应如下所示:After commenting out the login lines, the code follows:

  // Login to the service.
  // client.login('microsoftaccount')
  //    .then(function () {
    syncContext.initialize(store).then(function () {
      // Leave the rest of the code in this callback function  uncommented.
  // }, handleError);

现在,应用会在运行应用时与 Azure 后端同步。Now, the app syncs with the Azure backend when you run the app.

运行客户端应用Run the client app

启用脱机同步后,可在每个平台上至少运行一次客户端应用程序,以填充本地存储数据库。With offline sync now enabled, you can run the client application at least once on each platform to populate the local store database. 稍后,模拟脱机场景,并在应用处于脱机状态时修改本地存储中的数据。Later, simulate an offline scenario and modify the data in the local store while the app is offline.

(可选)测试同步行为(Optional) Test the sync behavior

本节对客户端项目进行修改,通过对后端使用无效的应用程序 URL 来模拟脱机场景。In this section, you modify the client project to simulate an offline scenario by using an invalid application URL for your backend. 添加或更改数据项时,这些更改保存在本地存储中,但在重新建立连接之前,这些更改不会同步到后端数据存储中。When you add or change data items, these changes are held in the local store, but are not synced to the backend data store until the connection is re-established.

  1. 在解决方案资源管理器中,打开 index.js 项目文件,并更改应用程序 URL,使其指向无效的 URL,如以下代码所示:In the Solution Explorer, open the index.js project file and change the application URL to point to an invalid URL, like the following code:

     client = new WindowsAzure.MobileServiceClient('http://yourmobileapp.chinacloudsites.cn-fail');
  2. 在 index.html 中,使用同一无效的 URL 更新 CSP <meta> 元素。In index.html, update the CSP <meta> element with the same invalid URL.

     <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: http://yourmobileapp.chinacloudsites.cn-fail; style-src 'self'; media-src *">
  3. 生成并运行客户端应用,请注意,如果应用在登录后尝试与后端同步,则会在控制台中记录异常。Build and run the client app and notice that an exception is logged in the console when the app attempts to sync with the backend after login. 添加的任何新项在推送到移动后端之前,只存在于本地存储中。Any new items you add exist only in the local store until they are pushed to the mobile backend. 客户端应用的行为就像它已连接到后端一样。The client app behaves as if it is connected to the backend.

  4. 关闭应用程序并重新启动它,以验证你创建的新项目是否已永久保存到本地存储中。Close the app and restart it to verify that the new items you created are persisted to the local store.

  5. (可选)使用 Visual Studio 查看 Azure SQL 数据库表,看看后端数据库中的数据是否未更改。(Optional) Use Visual Studio to view your Azure SQL Database table to see that the data in the backend database has not changed.

    在 Visual Studio 中,打开“服务器资源管理器” 。In Visual Studio, open Server Explorer. 导航到“Azure” ->“SQL 数据库” 中的数据库。Navigate to your database in Azure->SQL Databases. 右键单击数据库并选择“在 SQL Server 对象资源管理器中打开” 。Right-click your database and select Open in SQL Server Object Explorer. 现在便可以浏览 SQL 数据库表及其内容。Now you can browse to your SQL database table and its contents.

(可选)测试与移动后端的重新连接(Optional) Test the reconnection to your mobile backend

本节将应用重新连接到移动后端,可模拟重新回到联机状态的应用。In this section, you reconnect the app to the mobile backend, which simulates the app coming back to an online state. 登录时,数据将同步到移动后端。When you log in, data is synced to your mobile backend.

  1. 重新打开 index.js 并还原应用程序 URL。Reopen index.js and restore the application URL.

  2. 重新打开 index.html,更正 CSP <meta> 元素中的应用程序 URL。Reopen index.html and correct the application URL in the CSP <meta> element.

  3. 重新生成并运行客户端应用。Rebuild and run the client app. 应用在登录后尝试与移动应用后端进行同步。The app attempts to sync with the mobile app backend after login. 验证调试控制台中是否未记录任何异常。Verify that no exceptions are logged in the debug console.

  4. (可选)使用 SQL Server 对象资源管理器或 Fiddler 之类的 REST 工具查看更新后的数据。(Optional) View the updated data using either SQL Server Object Explorer or a REST tool like Fiddler. 请注意,数据已在后端数据库和本地存储之间进行同步。Notice the data has been synchronized between the backend database and the local store.

    请注意,数据已在数据库和本地存储之间进行同步,并包含在应用断开连接时添加的项目。Notice the data has been synchronized between the database and the local store and contains the items you added while your app was disconnected.

其他资源Additional resources

后续步骤Next steps