如果我有一个带有ajax调用的函数,它从数据库获取一些值,然后我需要将该值发送回php脚本等等,我应该如何声明这个变量?
function call(id){
$.ajax({
. . .
data: {id: id},
success: function(res){
window.id = res.id
}
});
}
//first call the function with a value
call(10);
//then call it with the returned value every time the btn gets clicked
$('#btn').click(function(){
call(window.id);
})
根据我的理解,使用这样的全局变量是不好的做法,因为全局范围已经很拥挤,并且脚本查找变量需要更长的时间。我可以以一种让我在不全局的情况下将其发回的方式定义该值吗?
最佳答案
避免全局变量的最简单方法是首先不在全局范围内工作。方法是创建一个 IIFE (立即调用函数表达式),这是一个全局范围内的匿名函数,但由于它是匿名的,因此它不会与另一个同名函数发生冲突。它会立即被调用,以便其中的代码可以执行(类似于 init
类型的操作)。然后,在该函数内您可以执行通常会执行的操作。然后您可以在此处创建 IIFE 作用域(非全局作用域)变量。
// IIFE wrapper
(function(){
let mainID = null; // IIFE scoped variable
function call(id){
$.ajax({
. . .
data: {id: id},
success: function(res){
mainID = res.id; // Set the IIFE scoped variable to the AJAX result
}
});
}
// Set up the event
$('#btn').click(function(){
all(res.id); // <-- And, you can use it anywhere in the IIFE
});
call(10); // first call the function with a value
})(); // <-- The extra set of parenthesis is what invokes the expression
另一方面,即使这样做,您的代码也将无法工作,因为您正在 AJAX 调用有机会完成之前设置按钮的 click
事件处理程序。仅仅因为该代码出现在异步代码之后,并不意味着它将在异步代码之后执行。异步操作的要点在于,我们不知道它何时完成,并且由于 JavaScript 在单线程环境中运行,当异步操作执行其业务时,当前函数将运行至完成。只有当前线程空闲后,才会调用异步操作的结果(成功回调)。如果事件处理程序依赖于 AJAX 调用的结果,则需要在“成功”回调中设置事件处理程序,从而使全局的需求变得毫无意义。不过,您仍然应该将所有代码放在 IIFE 中,因为这是最佳实践。
下面的示例显示了不同类型的异步操作(计时器),该操作仍然像显示问题的 AJAX 调用一样运行:
// Global variable
var result = null;
// Start an async operation that will execute the callback
// after three seconds:
setTimeout(function(){
result = "complete"
console.log("Async operation " + result);
}, 3000);
// This function will run before the async operation
// completes, so the use of the variable that is set
// by the async operation will fail
console.log("Local operation " + result);
所以实际上,您甚至不需要全局变量,只需将事件绑定(bind)代码移至成功回调中即可。从 UI Angular 来看,您可能希望按钮一开始处于禁用状态,然后在成功回调中启用它,以便在设置 click
处理程序之前无法单击该按钮。
// IIFE wrapper
(function(){
function call(id){
$.ajax({
. . .
data: {id: id},
success: function(res){
// Set up the event now that the AJAX call is complete
$('#btn').click(function(){
call(res.id);
});
}
});
}
call(10); // first call the function with a value
})(); // <-- The extra set of parenthesis is what invokes the expression
这是整个事情的一个工作示例:
(function(){
// IIFE scoped variables
let btn = document.querySelector("button");
let random = null;
function async(){
// Async operation complete!
// Generate a random number that simulates the
// DB response that would now be available
random = Math.floor(Math.random() * 11);
// Enable the button:
btn.removeAttribute("disabled");
// Set up the button's click event handler
btn.onclick = function(){
console.log("Button clicked. ID = " + random);
async();
};
}
// Start an async operation that will execute the callback
// after three seconds:
setTimeout(async, 3000);
})();
<button type="button" disabled>Click Me</button>
关于javascript - 在这种情况下如何避免声明全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54161486/