清洁的集中导航设计?

时间:2015-08-21 13:26:28

标签: javascript asynchronous navigation code-structure

上下文

单页/ ajax网络应用

基本代码结构

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

Page / Tile Flow

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

问题

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

限制

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

目前提议的实施

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

总结一下,如果用户在呼叫进行过程中更改了位置,则在呼叫解决后,我们将无法导航,因为用户不希望在此时导航到“查看顺序”。

这有效,对吧?

Catch

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

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

4 个答案:

答案 0 :(得分:5)

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

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

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

通过这种方式,您的用户将拥有一致的用户体验,因为他们知道无论何时他们点击应用程序中的按钮,都会发生相同的事情(导航到视图),并且没有令人惊讶的自动重定向。

答案 1 :(得分:2)

鉴于您无法阻止用户在切片中导航,通知她有关计算延迟的信息并不能解决整个问题。您可以告诉用户预计完成时间,您可以显示进度条,然后您可以立即将她带到Review Order磁贴以等待结果,但是如果她离开磁贴,您就会离开原来的问题。

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

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

您可以在不修改现有呼叫的情况下向setLocation添加新参数。这仅需要intendedStartingPointsetLocation的参数列表中的最后一个参数。然后,您的新版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.
}

答案 2 :(得分:1)

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

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

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

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

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

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

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

答案 3 :(得分:0)

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

这意味着,if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate}是不够的。您必须执行if(intendedStartingPoint === Locationmanager.currentLocation && /* no information altered in the meantime*/) {//Navigate}之类的操作。

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

  • 提供在LocationManager
  • 中注册和管理长时间通话的方法
  • 应始终使用LocationManager
  • 注册长时间通话
  • LocationManager应确保最多只有一个长时间通话处于活动状态
  • 如果发生任何位置更改,则必须使所有(或一个活动的)长时间运行的呼叫无效
  • 长时间运行的呼叫的回叫应该检查它是否已经无效,并且只有在这种情况下才会导航。 LocationManager可以统一的方式为所有回拨做到这一点。
  • 新的长时间呼叫可以替换/使已经在运行的呼叫无效,或者被拒绝。

我希望在你的具体情况下这是有道理的。