上下文
单页/ ajax网络应用
基本代码结构
LocationManager (负责更新浏览器哈希并将应用程序位置切换到其他磁贴)
Page / Tile Flow
基本信息>家庭信息>车辆信息>购买选项>查看订单>输入付款并提交
问题
当用户从“购买选项”导航到“审阅订单”时,会进行长时间(5-8秒)的服务调用以计算订单详细信息。在呼叫解决后,回调旨在将用户导航到“查看订单”页面。问题是,如果用户在此期间点击回来并返回到家庭信息,一旦通话结算,他们将“自动”带到审核订单。非常尴尬的用户体验。
限制
取消通话不是一种选择。需要一个解决方案来处理导航。
目前提议的实施
在进行calculateOrder调用之前保存“currentLocation”。
将回调中的“currentLocation”传递给setLocation方法作为setStartingPoint。
内部setLocation方法if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate}
总结一下,如果用户在呼叫进行过程中更改了位置,则在呼叫解决后,我们将无法导航,因为用户不希望在此时导航到“查看顺序”。
这有效,对吧?
Catch
我们在app中有很多地方可以在长时间运行的调用的回调中调用setLocation。这意味着我将不得不使用新参数--wartingStartingPoint更新所有setLocation调用。虽然这对我来说很有意义,但它看起来似乎有可能变得有点混乱。
关于如何清理和集中它的任何想法?
答案 0 :(得分:5)
因此,现在用户可以单击“购买选项”页面上的“计算”按钮。然后你会显示某种加载指示器(希望如此)
并向连续附加setLocation('ReviewOrder')
的服务器发送异步请求。应用程序中有很多地方使用这种模式。
意外(从用户的角度来看)重定向的问题是存在的,因为使用这种方法服务器数据检索和UI导航是耦合的。想到的解决方案是将它们分离并删除setLocation
个调用
从所有长期运行的请求延续。它可以按以下方式工作。
当用户单击“计算”按钮时,您启动异步请求,同时立即导航到“审阅订单”页面(从用户体验的角度来看这很重要,因为用户现在清楚地了解了“计算”按钮导航到“查看订单”)。在“审核订单”页面上,显示一个加载指示符,表示“请等待,大约还剩10秒......”#39;请求完成后,隐藏加载指示器并显示数据。
通过这种方式,您的用户将拥有一致的用户体验,因为他们知道无论何时他们点击应用程序中的按钮,都会发生相同的事情(导航到视图),并且没有令人惊讶的自动重定向。
答案 1 :(得分:2)
鉴于您无法阻止用户在切片中导航,通知她有关计算延迟的信息并不能解决整个问题。您可以告诉用户预计完成时间,您可以显示进度条,然后您可以立即将她带到Review Order磁贴以等待结果,但是如果她离开磁贴,您就会离开原来的问题。
如果用户选择在所有这些信息之后离开,她必须有意识地决定中断诉讼程序。将她送回审查订单将是一个糟糕的用户体验。现在怎么办?
您非常合理地建议,使用calculateOrder
发送的回调函数应将intendedStartingPoint
参数传递给setLocation
。您担心这会要求您修改对setLocation
的每次调用以适应新参数。从不担心,JavaScript提供了一种解决这一难题的巧妙方法。
您可以在不修改现有呼叫的情况下向setLocation
添加新参数。这仅需要intendedStartingPoint
是setLocation
的参数列表中的最后一个参数。然后,您的新版setLocation
可以检查intendedStartingPoint
的值,看看它是undefined
。
如果intendedStartingPoint
为undefined
,您知道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
可以统一的方式为所有回拨做到这一点。我希望在你的具体情况下这是有道理的。