很多人将他们的应用程序建模为一长串回调,调用流程中的下一步。我正在努力避免这种情况。我正在做一个培训网站中弹出的“测验”。我使用 when/then 范例来启动一切,我喜欢它的外观:
$.when(
quiz_getQuizData(courseId),
quiz_loadDependencies()
).then(function(){
quiz_prepareData();
$.when(
quiz_buildPage(target)
).then(function(){
quiz_initEventHandlers();
quiz_start();
[here?]
});
});
它清楚地表明,首先您获取数据和依赖项,然后准备数据并构建页面,然后初始化事件处理程序并开始测验。
如果我进一步扩展以使“参加测验”成为一个异步过程会怎样?目前,我有一个回调,当某些函数决定测验完成时将调用该回调。但为了在一个地方显示测验的整个生命周期,也许我应该添加
$.when(
quiz_getResponses() /* <-- user takes 20 min to answer some questions*/
).then(function(){
$.when(
quiz_submit()
).then(function(){
quiz_finish();
callback();
});
});
问题是,quiz_getResponses 实际上只会创建一个延迟对象,然后代码中某处的“我完成了”按钮将解决它,然后触发其余的时间。
我不喜欢它,因为 getResponses 并没有真正得到响应(即使重命名,它也不会做任何事情,真的)。而且,要找到谁在“解析”该对象仍然有些困难。所以这似乎不是一个好的模式。
那么我如何才能将整个测验建模为一系列异步事件呢?将上面的代码添加到[此处]的第一个代码中是否会非常糟糕(我认为是的,因为它太嵌套了)。
处理这个想法的好模式是什么
- 几个异步初始化步骤
- 用户执行操作时等待时间较长
- 几个异步结束步骤
更新 对于后代来说,这就是该序列的计算方式:
$.when(
quiz_getQuizData(quizOptions['courseId']),/* submit courseId, wait for quiz data (questions, choices) */
quiz_loadDependencies() /* wait for yepnope to load javascript and css dependencies */
).then(function(){
quiz_prepareData(); /* build object for rendering quiz template */
$.when(
quiz_buildPage(targetSelector) /* wait for template, render page into target */
).then(function(){
quiz_initEventHandlers(); /* add handlers to click events */
quiz_start(); /* do any final preparations, show the quiz */
$.when(
quiz_getResponses() /* wait for user to answer questions (or time run out) */
).then(function(){
$.when(
quiz_getResults() /* submit responses, wait for results */
).then(function(){
$.when(
quiz_showResults() /* show results, wait for user to close */
).then(function(){
var result=quiz_finish(); /* do any final operations, hide and destroy the quiz */
callback(result); /* notify page that quiz is over, send result */
});
});
});
});
});
最佳答案
不,图案完全没问题。等待用户输入是一项异步任务,可以而且应该使用 Promise 对其进行建模。
The thing is, quiz_getResponses would really just create a deferred object and then an "I'm done" button somewhere in the code would resolve it. I don't like it because getResponses doesn't actually DO anything. And it would still be somewhat not straightforward to find who is "resolving" the object.
您的 quiz_getResponses
函数应创建并显示按钮,并在其上安装点击监听器(或在如果您想将按钮放入 HTML 中,至少是后者)。它甚至可能在单击按钮后(或测验超时等)负责清理按钮。
事实上,创建一个全局延迟并让任意点击处理程序(或者实际上,任何东西)解析它是一种反模式。按钮代码不应位于“某处”,而应位于 quiz_getResponses
函数内。
关于javascript - 将 "quiz"建模为异步 "long running process",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26765324/