javascript - 在这种情况下如何避免声明全局变量?

标签 javascript jquery ajax

如果我有一个带有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/

相关文章:

php - 获取多个文本字段的值将其存储到 var 并将其发送到 CodeIgniter

IE 的 JavaScript 条件注释

javascript - 每次单击按钮时使 div 向一个方向移动

jquery - 使用 JQuery 在 Internet Explorer 中进行 CORS 身份验证

javascript - 将插入符号放在动态生成的跨度之外

javascript - 尝试从整页中获取所有复选框

javascript - jQuery ajax,附有var的数据字段的名称

javascript - 当中继器内未选中复选框时禁用文本框

ajax - 从Spring Controller返回ajax调用的错误消息字符串的最佳实践是什么?

javascript - 为什么ajax请求时缓存不清晰?