将“测验”建模为异步“长时间运行的过程”

时间:2014-11-05 19:20:32

标签: javascript button asynchronous promise jquery-deferred

许多人将他们的应用程序建模为一长串回调,这些回调称为流程的下一步。我试图避免这种情况。我正在进行一项在测试网站内弹出的“测验”。我正在使用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没有真正获得响应(甚至重命名,它不会做任何事情,真的)。而且,找到谁“解析”对象仍然有点不直接。所以它似乎不是一个好的模式。

那么我如何为整个测验建模一系列异步事件?将上面的代码添加到[here]的第一个代码(我想是这样,因为它太嵌套了)会不会很糟糕。

处理

的想法的好模式是什么
  • 几个异步初始化步骤
  • 用户做事时等待很长时间
  • 几个异步结束步骤

更新 对后人来说,这就是序列的实现方式:

$.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               */
                    });
                });
            });
        });
    });

1 个答案:

答案 0 :(得分:1)

不,模式完全没问题。等待用户输入是一个异步任务,可以 - 而且应该 - 使用promise建模。

  

问题是,quiz_getResponses实际上只是创建一个延迟对象,然后代码中某处的“我已完成”按钮将解析它。我不喜欢它因为getResponses实际上没有做任何事情。找到谁正在“解决”这个对象仍然有点不直接。

您的quiz_getResponses功能应创建显示按钮并在其上安装点击监听器(或至少后者)如果你想把按钮放在你的HTML中)。它甚至可以在点击按钮后清理按钮(或测验超时等)。

确实,创建一个全局延迟并让任意点击处理程序(或实际上,任何东西)解决它是一个反模式。按钮代码不应该是“某处”,而是在quiz_getResponses函数内。