>웹 프론트엔드 >JS 튜토리얼 >기본 JavaScript는 Ajax 비동기 요청을 구현합니다.

기본 JavaScript는 Ajax 비동기 요청을 구현합니다.

韦小宝
韦小宝원래의
2018-01-16 11:10:101706검색

ajax는 이제 매우 인기 있는 기술입니다. 이제 JQuery나 일부 타사 플러그인, 심지어 Microsoft에서 제공하는 일부 컨트롤을 사용하여 ajax 기능을 구현할 수도 있지만 다음은 그 원리를 이해하는 것입니다. 순수 JavaScript를 사용하여 Ajax 함수를 구현하여 원리를 명확히 하는 방법을 보여주기 위해 서버 측 함수를 가져옵니다.

프런트 엔드 페이지 개발 과정에서 Ajax 요청은 종종 양식 데이터를 비동기식으로 제출하는 데 사용됩니다. 페이지를 비동기적으로 새로 고칩니다.

일반적으로 Jquery에서는 $.ajax, $.post, $.getJSON을 사용하면 매우 편리하지만 때로는 ajax 기능만 필요한 경우도 있으므로 Jquery를 도입하는 것은 비용 효율적이지 않습니다.

다음에는 기본 JavaScrpit을 사용하여 간단한 Ajax 요청을 구현하고, Ajax 요청의 도메인 간 액세스 문제와 여러 Ajax 요청의 데이터 동기화 문제를 설명하겠습니다.

JavaScript는 Ajax 비동기 요청을 구현합니다

간단한 ajax 요청 구현
Ajax 요청의 원칙은 XMLHttpRequest 객체를 생성하고 이 객체를 사용하여 비동기적으로 요청을 보내는 것입니다.

function ajax(option) {
  // 创建一个 XMLHttpRequest 对象
  var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"),
    requestData = option.data,
    requestUrl = option.url,
    requestMethod = option.method;
  // 如果是GET请求,需要将option中的参数拼接到URL后面
  if ('POST' != requestMethod && requestData) {
    var query_string = '';
    // 遍历option.data对象,构建GET查询参数
    for(var item in requestData) {
      query_string += item + '=' + requestData[item] + '&';
    }
    // 注意这儿拼接的时候,需要判断是否已经有 ?
    requestUrl.indexOf('?') > -1
      ? requestUrl = requestUrl + '&' + query_string
      : requestUrl = requestUrl + '?' + query_string;
    // GET 请求参数放在URL中,将requestData置为空
    requestData = null;
  }
  // ajax 请求成功之后的回调函数
  xhr.onreadystatechange = function () {
    // readyState=4表示接受响应完毕
    if (xhr.readyState == ("number" == typeof XMLHttpRequest.DONE ? XMLHttpRequest.DONE : 4)) {
      if (200 == xhr.status) { // 判断状态码
        var response = xhr.response || xhr.responseText || {}; // 获取返回值
        // if define success callback, call it, if response is string, convert it to json objcet
        console.log(response);
        option.success && option.success(response); // 调用回调函数处理返回数据
        // 可以判断返回数据类型,对数据进行JSON解析或者XML解析
        // option.success && option.success('string' == typeof response ? JSON.parse(response) : response);
      } else {
        // if define error callback, call it
        option.error && option.error(xhr, xhr.statusText);
      }
    }
  };
  // 发送ajax请求
  xhr.open(requestMethod, requestUrl, true);
  // 请求超时的回调
  xhr.ontimeout = function () {
    option.timeout && option.timeout(xhr, xhr.statusText);
  };
  // 定义超时时间
  xhr.timeout = option.timeout || 0;
  // 设置响应头部,这儿默认设置为json格式,可以定义为其他格式,修改头部即可
  xhr.setRequestHeader && xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
  xhr.withCredentials = (option.xhrFields || {}).withCredentials;
  // 这儿主要用于发送POST请求的数据
  xhr.send(requestData);
}

위의 코드에는 자세한 설명이 포함되어 있으며 ajax의 원리는 일반적으로 XMLHttpRequest 객체를 사용하여 데이터를 전송합니다. 다음은 이 개체에 대한 보충 설명입니다.

XMLHttpRequest 개체

readyState 속성의 기본 속성에는 5개의 상태 값이 있습니다.

0: 초기화되지 않음: 초기화되지 않음. XMLHttpRequest 객체가 생성되었지만 초기화되지 않았습니다.
1: 로딩 중: 전송할 준비가 되었습니다.
2: 로드되었습니다.: 전송했지만 아직 응답을 받지 못했습니다.
3: 대화형입니다. 응답이 수신되고 있지만 아직 수신되지 않았습니다.
4: 예 완료됨: 응답이 수락되었습니다.
responseText: 서버가 반환한 응답 텍스트입니다. ReadyState>=3인 경우에만 값을 갖습니다. ReadyState=3인 경우 반환된 응답 텍스트가 불완전합니다. ReadyState=4인 경우에만 전체 응답 텍스트가 수신됩니다.

responseXML: 응답 정보는 xml이며 Dom 개체로 구문 분석될 수 있습니다.

status: 서버의 Http 상태 코드가 200이면 OK, 404는 찾을 수 없음을 의미합니다.

statusText: 서버 http 상태 코드의 텍스트입니다. 예를 들어 확인, 찾을 수 없음입니다.

XMLHttpRequest 객체의 기본 메소드

open(method, url, asyn): XMLHttpRequest 객체를 엽니다. 메소드에는 get, post, delete 및 put이 포함됩니다. url은 요청된 리소스의 주소입니다. 세 번째 매개변수는 비동기식 사용 여부를 나타냅니다. Ajax의 특성은 비동기 전송이기 때문에 기본값은 true입니다. 동기화가 사용되는 경우 거짓입니다.

send(body): Ajax 요청을 보냅니다. 전송되는 내용은 필수 매개변수일 수 있습니다. 매개변수가 없으면 직접 전송(null)

Usage method

위에서 정의한 ajax 함수를 직접 호출하여 해당 옵션과 매개변수를 전송합니다.

ajax({
  url: '/post.php',
  data: {
    name: 'uusama',
    desc: 'smart'
  },
  method: 'GET',
  success: function(ret) {
    console.log(ret);
  }
});

교차 도메인 요청 문제

Ajax 요청을 사용할 때 한 가지 문제인 교차 도메인 요청에 주의해야 합니다.

특별한 수단을 사용하지 않고 도메인 간 요청: 다른 도메인 이름 및 포트에서 URL 리소스를 요청할 때 Access-Control-Allow-Origin 관련 오류가 보고됩니다. 주된 이유는 크로스 도메인 리소스 요청이 이루어질 수 없도록 규정하는 브라우저의 동일 출처 정책 제한 때문입니다.

Solutions

다음은 몇 가지 간단한 솔루션입니다.

Ajax 헤더에 도메인 간 요청을 허용하는 헤더를 추가하려면 서버가 도메인 간 요청을 허용하는 헤더 추가에 협력해야 합니다. 다음은 POST 요청을 허용하는 도메인 간 헤더를 추가하는 PHP 예제입니다.

// 指定允许其他域名访问 
header('Access-Control-Allow-Origin:*'); 
// 响应类型 
header('Access-Control-Allow-Methods:POST'); 
// 响应头设置 
header('Access-Control-Allow-Headers:x-requested-with,content-type');

동적 scrpit 태그를 사용하여 scrpit 태그를 동적으로 생성하고 요청된 주소(JSONP 메서드)를 지정해야 합니다. 콜백을 연결해야 합니다. 태그가 성공적으로 로드된 후에 콜백 함수가 호출됩니다.

var url = "http://uusama.com", callbaclName = 'jsonpCallback';
script = document.createElement('script');
script.type = 'text/javascript';
script.src = url + (url.indexOf('?') > -1 ? '&' : '?') + 'callback=' + callbaclName;
document.body.appendChild(script);

콜백 함수를 전역 함수로 설정해야 합니다.

window['jsonpCallback'] = function jsonpCallback(ret) {}

여러 ajax 요청 데이터 동기화 문제

단일 ajax 반환 데이터가 비동기식으로 처리됩니다.
여러 ajax 요청은 서로 관련이 없습니다. Request 호출 후 별도로 전송되며, 요청 성공 후 자체 콜백 메서드를 호출하여 서로 영향을 미치지 않습니다.

Ajax 요청의 비동기 특성으로 인해 요청 완료에 의존하는 모든 작업은 콜백 함수 내부에 배치되어야 합니다. 그렇지 않으면 콜백 함수 외부에서 읽은 값이 비어 있게 됩니다. 아래 예를 보세요.

var result = null;
ajax({
  url: '/get.php?id=1',
  method: 'GET',
  success: function(ret) {
    result = ret;
  }
});
console.log(result); // 输出 null

콜백 함수에 결과 값을 설정했지만 마지막 줄의 console.log(result) 출력은 비어 있습니다.

Ajax 요청은 비동기식이므로 프로그램이 마지막 줄까지 실행될 때 요청이 완료되지 않고 값을 수정할 시간이 없습니다.

여기서는 성공 콜백 함수에 console.log(result) 관련 처리를 넣어야 합니다.

여러 Ajax 반환 데이터 문제

Ajax 요청이 여러 개 있으면 상황이 조금 복잡해집니다.

여러 Ajax 요청이 순차적으로 실행되고 그 중 하나가 다음 요청이 수행되기 전에 완료되면 다음 요청은 이전 요청의 콜백에 배치될 수 있습니다.

比如有两个ajax请求,其中一个请求的数据依赖于另外一个,则可以在第一个请求的回调里面再进行ajax请求:

// 首先请求第一个ajax
ajax({
  url: '/get1.php?id=1',
  success: function(ret1) {
    // 第一个请求成功回调以后,再请求第二个
    if (ret1) {
      ajax({
        url: '/get2.php?id=4',
        success:function(ret2) {
          console.log(ret1);
          console.log(ret2)
        }
      })
    }
  }
});

// 也可以写成下面的形式
// 将第二个ajax请求定义为一个函数,然后调用
var ajax2 = function(ret1) {
  ajax({
    url: '/get2.php?id=4',
    success:function(ret2) {
      console.log(ret1);
      console.log(ret2)
    }
  });
};
ajax({
  url: '/get1.php?id=1',
  success: function(ret1) {
    if(ret1){
      ajax2(ret1); // 调用第二个ajax请求
    }
  }
});

如果不关心不同的ajax请求的顺序,而只是关心所有请求都完成,才能进行下一步。

一种方法是可以在每个请求完成以后都调用同一个回调函数,只有次数减少到0才执行下一步。

var count = 3, all_ret = []; // 调用3次
ajax({
  url: '/get1.php?id=1',
  success:function(ret) {
    callback(ret); // 请求成功后调用统一回调,次数减1
  }
});
ajax({
  url: '/get2.php?id=1',
  success:function(ret) {
    callback(ret);
  }
});
ajax({
  url: '/get3.php?id=1',
  success:function(ret) {
    callback(ret);
  }
});
function callback(ret) {
  // 当调用3次以上以后,说明3个ajax军完成
  if (count > 0) {
    count--; // 每调用一次,次数减1
    // 可以在这儿保存 ret 到全局变量
    all_ret.push(ret);
    return;
  } else { // 调用三次以后
    // todo
    console.log(ret);
  }
}

另一种方法是设置一个定时任务去轮训是否所有ajax请求都完成,需要在每个ajax的成功回调中去设置一个标志。

这儿可以用是否获得值来判断,也可以设置标签来判断,用值来判断时,要注意设置的值和初始相同的情况。

var all_ret = {
  ret1: null, // 第一个ajax标识
  ret2: null, // 第二个ajax标识
  ret3: null, // 第三个ajax标识
};
ajax({
  url: '/get1.php?id=1',
  success:function(ret) {
    all_ret['ret1'] = ret; // 修改第一个ajax请求标识
  }
});
ajax({
  url: '/get2.php?id=1',
  success:function(ret) {
    all_ret['ret2'] = ret; // 修改第二个ajax请求标识
  }
});
ajax({
  url: '/get3.php?id=1',
  success:function(ret) {
    all_ret['ret3'] = ret; // 修改第三个ajax请求标识
  }
});
var repeat = setInterval(function(){
  // 遍历是否所有ajax请求标识都已被修改,以此判断是否所有ajax请求都已完成
  for(var item in all_ret) {
    if (all_ret[item] === null){
      return;
    }
  }
  // todo, 到这儿所有ajax请求均已完成
  clearInterval(repeat);
}, 50); // 调用次数可以适当调整,不应设的过小或者过大

以上就是本篇文章的所有内容,希望对大家学习提供到帮助!!

相关推荐:

javascript匹配js中注释的正则表达式代码

Javascript中从学习bind到实现bind的过程详解

JavaScript门面模式实例详解

위 내용은 기본 JavaScript는 Ajax 비동기 요청을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.