简单地说,我试图根据我从服务器通过AJAX请求检索的场景动态生成AJAX请求。
这个想法是:
最大的想法是,我可以根据服务器提供的场景动态更改第二个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"
}
}
]
}
答案 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();