基于场景动态生成AJAX请求

时间:2015-02-09 20:21:39

标签: javascript jquery ajax

简单地说,我试图根据我从服务器通过AJAX请求检索的场景动态生成AJAX请求。

这个想法是:

  1. 服务器提供"场景"让我生成一个AJAX请求。
  2. 我根据场景生成一个AJAX请求。
  3. 然后我在循环中反复重复这个过程。
  4. 最大的想法是,我可以根据服务器提供的场景动态更改第二个AJAX请求。

    我有这个工作,但我觉得我这样做的方式非常混乱。有没有更好的方法来思考这个问题?也许承诺?如果有人可以请审查这个并提供有关如何清理它的反馈或建议 - 非常感谢。

    以下是我的代码:http://jsfiddle.net/6jph0e98/ (请打开控制台以查看所有操作)

    作为参考,以下是我目前使用的方案数据:

        var scenario = {
            "base": {
                "frequency": "5000"
            },
            "endpoints": [
                {
                    "method": "GET",
                    "type": "JSON",
                    "endPoint": "https://api.github.com/users/alvarengarichard",
                    "queryParams": {
                        "objectives": "objective1, objective2, objective3"
                    }
                }
            ]
        }
    

1 个答案:

答案 0 :(得分:2)

这是我的2美分:http://jsfiddle.net/3Lddzp9j/6/

是的,我认为你可以通过链接承诺来更优雅地做到这一点。所以我想出了我认为你的应用程序做了什么,以及如何通过链接这些承诺来做到这一点。有趣的是,某些步骤已经返回promises(jQuery AJAX调用),但其他步骤没有。对于那些 - 我们必须创建我们自己的承诺,立即解决。然后是我们在承诺中包含的超时。

此外,我尝试使用一些JS最佳实践,例如通过将它们包装在IIFE中并应用module pattern来将事物排除在全局空间之外。 这使您的应用程序的整体控制流程变得美观和干净恕我直言:

    var run = function() {
        getScenario()
        .then(mapToInstruction)
        .then(waitForTimeout)
        .then(callApi)
        .then(handleResults)
        .then(run);
    };

并且还隐藏私有成员并且只暴露run()方法:

    return {
        // This will expose only the run method
        // and will keep all other functions private
        run : run
    }

希望它有所帮助 - 让我知道你的想法。这是完整的来源,有评论:

// First of all - I'm using the javascript module pattern here
// this will all be much more easy once ES6 it out, but this will
// have to do for now.
// Also, I'm importing jQuery into the module as you can see, which
// is wrapped inside the IIFE ( Google it ) which keeps things nicely
// out of the global scope.
var App = (function ($) {

    // Gets the scenario from the API - $.get is just some syntactic
    // sugar for $.ajax with GET as method - NOTE: this returns a promise
    var getScenario = function () {
        console.log('Getting scenario ...');
        return $.get('http://demo3858327.mockable.io/scenario');
    };

    // The result of the previous promise is passed into the 
    // next as we're chaining. So the data will contain the 
    // result of getScenario
    var mapToInstruction = function (data) {
        // We map it onto a new instruction object
        var instruction = {
            method: data.endpoints[0].method,
            type: data.endpoints[0].type,
            endpoint: data.endpoints[0].endPoint,
            frequency: data.base.frequency
        };

        console.log('Instructions recieved:');
        console.log(instruction);

        // And now we create a promise from this
        // instruction so we can chain it
        var deferred = $.Deferred();
        deferred.resolve(instruction);
        return deferred.promise();
    };

    // This wraps the setTimeout into a promise, again
    // so we can chain it
    var waitForTimeout = function(instruction) {
        console.log('Waiting for ' + instruction.frequency + ' ms');
        var deferred = $.Deferred();
        setTimeout(function() {
            deferred.resolve(instruction)
        }, instruction.frequency); 
        return deferred.promise();
    };

    // Final step: call the API from the 
    // provided instructions
    var callApi = function(instruction) {
        console.log('Calling API with given instructions ...');
        return $.ajax({
            type: instruction.method,
            dataType: instruction.type,
            url: instruction.endpoint
        });
    };

    var handleResults = function(data) {
        console.log("Handling data ...");
        var deferred = $.Deferred();
        deferred.resolve();
        return deferred.promise();
    };

    // The 'run' method
    var run = function() {
        getScenario()
        .then(mapToInstruction)
        .then(waitForTimeout)
        .then(callApi)
        .then(handleResults)
        .then(run);
    };

    return {
        // This will expose only the run method
        // and will keep all other functions private
        run : run
    }
})($);

// ... And start the app
App.run();