6

语境

单页/ajax 网络应用

基本代码结构

LocationManager(负责更新浏览器哈希并将应用程序位置切换到不同的磁贴)

页面/图块流

基本信息 > 家庭信息 > 车辆信息 > 购买选项 > 查看订单 > 输入付款并提交

问题

当用户从采购选项导航到查看订单时,会进行长时间(5-8 秒)的服务调用来计算订单详细信息。在呼叫解决后,回调旨在将用户导航到“查看订单”页面。问题是,如果用户在此期间点击返回并返回家庭信息,一旦呼叫解决,他们将被“自动”带到查看订单。非常尴尬的用户体验。

限制

取消通话不是一种选择。需要一个解决方案来处理导航。

当前提议的实施

在进行 calculateOrder 调用之前保存“currentLocation”。将回调中的“currentLocation”作为expectStartingPoint 传递给setLocation 方法。内部 setLocation 方法if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate}

总而言之,如果用户在通话进行时更改了位置,那么在通话解决后,我们将不会导航,因为用户不希望此时导航到 Review Order。

这行得通,对吧?

抓住

我们在应用程序中有很多地方在回调中调用 setLocation 以进行长时间运行的调用。这意味着我将不得不使用一个新参数--expectedStartingPoint 来更新所有的 setLocation 调用。虽然这对我来说很有意义,但它似乎确实有可能变得有点混乱。

关于如何清理和集中它的任何想法?

4

4 回答 4

5

因此,现在用户可以单击“购买选项”页面上的“计算”按钮。然后,您会显示某种加载指示器(希望如此),并向服务器发送一个异步请求,并setLocation('ReviewOrder')附加在一个延续中。应用程序中有很多地方使用这种模式。

存在意外(从用户的角度)重定向的问题,因为通过这种方法,服务器数据检索和 UI 导航是耦合的。想到的一个解决方案是将它们解耦并setLocation从所有长期运行的请求延续中删除调用。它可以通过以下方式工作。

当用户单击“计算”按钮时,您会启动一个异步请求,同时立即导航到“查看订单”页面(从用户体验的角度来看,这很重要,因为用户现在清楚地了解“计算”按钮导航到“查看订单”)。在 Review Order 页面上,显示一个加载指示器,上面写着“请稍候,还剩大约 10 秒...” 当请求完成时,隐藏加载指示器并显示数据。

这样,您的用户将拥有一致的用户体验,他们知道每当他们单击应用程序中的按钮时都会发生相同的事情(他们导航到视图),并且不会出现令人惊讶的自动重定向。

于 2015-08-27T14:21:59.860 回答
2

鉴于您无法阻止用户在图块之间导航,通知她计算延迟并不能解决整个问题。您可以告诉用户预计完成的时间,您可以显示进度条,并且您可以立即将她带到 Review Order 磁贴以等待结果,但如果她导航离开磁贴,您将留下您的原来的问题。

如果用户在所有这些信息之后选择离开,她一定是有意识地决定中断程序。将她送回审查订单将是糟糕的用户体验。现在怎么办?

您相当合理地建议发送的回调函数calculateOrder应该将intendedStartingPoint参数传递给setLocation. 您担心这会要求您修改每个调用以setLocation适应新参数。不用担心,JavaScript 提供了一种巧妙的方法来解决这个难题。

您可以在setLocation不修改现有调用的情况下添加新参数。这仅要求它是的参数列表intendedStartingPoint中的最后一个参数。setLocation然后你的新版本setLocation可以检查 的值,intendedStartingPoint看看它是否是undefined.

如果intendedStartingPointundefined,您知道setLocation正在接收旧电话之一,即未通过的电话intendedStartingPoint。在这些情况下,您忽略intendedStartingPoint并像以前一样继续。否则,您将intendedStartingPoint与当前位置进行比较,并根据比较结果进行操作。

更好的方法是使新参数不是intendedStartingPoint,而是一个名为的对象,该对象options包含intendedStartingPoint作为其属性之一。setLocation如果将来需要,这允许您传递更多可选值。

的新行为setLocation非常简单。在设置新位置之前,请检查是否intendedStartingPoint等于当前位置。如果是,您不必做任何事情,因为用户已经在她打算去的地方。但如果 与intendedStartingPoint当前位置不同,则用户已导航离开,因此您可以执行以下操作:

if (LocationManager.currentLocation !== options.intendedStartingPoint) {
  // Tell the user that the calculation has finished.
  // Ask her if she wants to return to Review Order now.
}
于 2015-08-29T11:17:55.633 回答
1

首先,通过异步调用计算订单详细信息,并通过 javascript 向最终用户显示/模拟进度条。

第二件事:不要ReviewOrder在服务回调函数中强制打开瓷砖。当服务完成计算时,您的回调函数会检查当前的磁贴,如果不是ReviewOrder磁贴,则将计算的信息存储在会话或本地存储中。

当用户浏览磁ReviewOrder贴时,将来自用户的订单详细信息与存储的订单详细信息进行比较(例如,通过散列函数)。

如果用户订单详情和存储订单详情的哈希码相同,则显示保存的订单信息,否则再次调用服务。

重要提示:为防止订单伪造,请考虑以下方式:

在服务器上计算订单详细信息后,生成唯一的订单 ID,并将其返回给用户。然后将计算出的订单详细信息与此 ID 一起存储在服务器数据库中。如果用户没有更改订单详细信息,您的脚本将仅将此订单 ID 发布到服务器作为标志,该订单已被接受。然后读取您的数据库并按此 ID 处理订单。

如果订单未完成,则使用计划任务,从未完成的订单中清理您的数据库(例如 - 订单,24 小时前计算,但仍未完成)。

于 2015-08-27T16:49:26.610 回答
0

首先,如果用户能够返回并更改之前页面上输入的任何信息,则必须使任何未决的服务调用无效。如果基于过时信息的服务调用返回,则必须将其丢弃。

这意味着,if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate}还不够。你必须做类似的事情if(intendedStartingPoint === Locationmanager.currentLocation && /* no information altered in the meantime*/) {//Navigate}

现在对于您的设计问题:如果没有任何具体代码,构建它有点困难,但您可以执行以下操作:

  • 提供方法来注册和管理长时间运行的呼叫LocationManager
  • 长时间运行的呼叫应始终向LocationManager
  • LocationManager应确保在某一时刻最多有一个长时间运行的呼叫处于活动状态
  • 如果发生任何位置更改,则必须使所有(或一个活动的)长时间运行的呼叫无效
  • 长时间运行的调用的回调应该检查它是否已经失效,并且只有在这种情况下才导航。LocationManager可以针对所有回调以统一的方式执行此操作。
  • 新的长时间运行的呼叫可以替换/使已经运行的呼叫无效或被拒绝,如您所愿。

我希望这对您的具体情况有意义。

于 2015-08-27T14:31:42.210 回答