我正在从另一个应用程序中提取 json,只有当用户在该应用程序中执行某些操作时,它才会被传递。
一旦我将它拉入,我就会检查它是否等于 1,然后有很多其他函数取决于需要执行的 true 或 false,并且只有在这个函数运行之后。
我可以将我所有的函数都放在 if 语句中,但是有没有更好的方法使用回调?
function retrieveData (retrieveDataJson){
data = JSON.parse(retrieveDataJson);
user = data.id;
if (user === 1) {
//do some stuff
}
else {
// do some other stuff
}
}
最佳答案
就编程风格而言,“更好”很难定义,因此在不了解您正在做什么以及您的代码结构如何的情况下,很难对您的问题给出“最佳”答案。
也就是说,一个好的经验法则是尝试根据描述问题的方式组织代码,而不是编写只关心控制流的代码。但这不是硬性规定,一方面,您要避免做任何事情的庞大函数,但另一方面,您要避免太小且跳来跳去调用其他函数或回调的函数。
首先,让我们假设您的代码只是同步的。大多数语言都是这样,很遗憾 Javascript 强制回调给您。您可以做的一件事是创建接收参数并返回适当值的函数。例如:
//This puts the "is user admin" logic in a single place
//Also note how we can give a good name for the function. If you have a
//hard time naming the function its a hint that maybe you shouldn't be creating
//the function in the first place.
function isAdmin(userData){
return userData.id === 1;
}
如果只是几行代码只用一次,可以直接内联
// Names like "process X" or "do X" are not very descriptive.
//See what I mean by it would be good to know extra context?
function processUser(userData){
// Your AJAX code should handle the JSON.Parse.
// I prefer having the code that does the work receive the JS objects
// because that makes things easier to test and to integrate with other JS code
// (no need to convert things to string just to pass to this function)
if(isAdmin(userData)){
//do
//some stuff
return someValue;
}else{
//do some other stuff
return someOtherValue;
}
}
请注意,我在这里添加了明确的“返回”。即使您的代码实际上没有返回任何内容,这也有助于理解向回调的过渡。
如果您的代码变得太大,您可以将其移至其他函数:
function processAdmin(user){
// dozens of lines of code...
return someValue;
}
function processUnpriviledgedUser(user){
//...
return someOtherValue;
}
function processUser(userData){
if(isAdmin(userData)){
return processAdminUser(userData);
}else{
return processUnpriviledgedUser(userData);
}
}
function fetchUser(){
//lets pretend that AJAX is synchronous for a moment...
var rawData = $.magicAjax("www.example.com");
var user = JSON.Parse(data);
var val = proccessUser(user);
return val;
}
请注意,我们通过函数免费获得的一件事是我们可以从多个地方调用它们:
var result = proccessUnpriviledgedUser({id:2, name:"hugomg"});
console.log( result );
现在,让我们开始回调。如果您所有的“processUser”内容都是同步的,您可能可以像我之前解释的那样使用普通函数重构它。不幸的是,如果您想在内部执行任何 AJAX 调用或其他异步操作,您不能像以前那样依赖 return
语句。相反,您需要将它们替换为 onDone
回调,该回调接收您本应返回的内容作为参数。
例如,我们的 processUser 可能看起来像
function processUser(userData, onDone){
if(isAdmin(userData)){ // <-- we can still use sync code when not doing IO
$.ajax("bla", {success: function(){
//blaz;
onDone(someValue);
});
}else{
//
}
}
function fetchUser(onDone){
$.ajax("www.example.com", {
success: function(data){
var user = JSON.Parse(data);
proccessUser(function(val){
onDone(val);
});
}
});
}
function main(){
fetchUser(function(val){
console.log("Fetched the user", val);
});
}
请注意我们如何使用与在单独函数中拆分代码相同的规则 - 关于代码大小和名称的相同想法仍然适用。唯一的区别是执行异步操作的函数需要使用回调而不是 return
。请特别注意我们是如何将 onDone 回调添加到 fetchUser 和 proccessUser 的。我们不仅创建了自己的异步函数,而且回调参数意味着我们不需要对函数结束后调用的内容进行硬编码——就像 return
返回调用我们的任何调用函数一样, onDone
回调意味着我们跳转到调用者希望我们进行的任何回调(而不是在我们完成后总是跳转到同一个地方)。
proccessUnpriviledgedUser({id:2, name:"hugomg"}, function(result){
console.log(result);
});
最后,我想指出异步代码的一大缺点是错误处理。为了像跨同步函数一样处理异步函数中的“try-catch”,除了 onDone
回调之外,您可能还需要传递 onError
回调。因为这是非常样板化的并且很容易正确,所以如果您开始编写非平凡的异步代码,我建议您使用某种库来帮助管理您的异步代码(基于 promise 或基于 cb 的应该没问题)。
关于json 解析后的 Javascript 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23811889/