前端點滴(JS核心)(一)---- 回調函數、Ajax基礎(一)

一、回調函數

1. 函數也是對象

JavaScript 中處處皆對象,函數也不例外。
那麼如何理解函數也是對象呢?這裏主要要表達的是函數也可以使用對象那樣的點語法。比如前面學習的Person.prototype;
比如在函數內部,可以使用“函數.length”來表示函數的形參個數,可以使用“函數.name”來獲取當前的函數名。

function Person(x,y){
	console.log(Person.length);  //=> 2
	console.log(Person.name);  //=>  Person
}
Person(1,2);

2. 函數也是值

JavaScript 語言將函數看作一種 值,與其它值(數值、字符串、布爾值等等)地位相同。凡是可以使用值的地方,就能使用函數。比如,可以把函數賦值給變量或者對象的屬性值,也可以當作參數傳入其他函數,或者作爲函數的結果返回。函數只是一個可以執行的值,此外並無特殊之處。
由於函數與其他數據類型地位平等,所以在 JavaScript 語言中又稱函數爲 第一等公民。

/* 當作一個值,賦值給一個變量 */
function a(){
	console.log(1);
}
var b = a;  // 將函數當作一個值,賦值給一個變量
b(); //=> 1

var c = function(){  // 將函數當作一個值,賦值給一個變量
	console.log(1);
}
c(); //=> 1

/* 當作一個對象成員的成員值 */
var obj = {
	name:'chen',
	say:function(){  // 將函數當作一個對象屬性的值
		console.log(1);
	}
}
obj.say(); //=> 1

/* 當作一個返回值 */
function fn1(){
var b = 1;
function fn2(){
	console.log(b++);
}
return fn2
}
var fn = fn1();
fn();  //=> 1
fn();  //=> 2
fn();  //=> 3

/* 當作一個參數進行傳遞 */
function callback(a){ 
	console.log(a);
}
function fn(callback){  // 將函數當作一個參數進行傳遞(回調函數)
	var a = 1;
	callback(a);
}
fn(callback); //=> 1

3. 函數可以作爲參數傳遞(回調函數)

在JavaScript中,回調函數具體的定義爲:函數A作爲參數(函數引用)傳遞到另一個函數B中,並且這個函數B執行函數A。我們就說函數A叫做回調函數。如果沒有名稱(函數表達式),就叫做匿名回調函數。

來一個具體的實例:

function callback(a){ 
	console.log(a);
}
function fn(callback){
	var a = 1;
	callback(a);
}
fn(callback); //=> 1

其中,下述函數可以稱爲獲取函數(通過參數a,帶有獲取功能)

function callback(a){ 
	console.log(a);
}

而下述函數被稱爲資源函數(函數內自帶資源,或者通過某些方法獲得的資源,通過參數引入獲取函數,使得函數與函數間具有通訊功能)

function fn(callback){
	var a = 1;
	callback(a);
}

資源函數中引入獲取函數,獲取資源

fn(callback);

匿名回調函數
非匿名函數,傳遞的是函數名的應用。
而匿名函數就是在傳參過程中直接傳遞函數,因爲函數可以作爲參數傳遞。

function fn(callback){
	var a = 1;
	callback(a);
}
fn(function (a){console.log(a)})  // 匿名回調函數,回調函數不帶名字。

4. 回調函數的執行時機

回調函數,一般在同步情境下是最後執行的,而在異步情境下有可能不執行,因爲事件沒有被觸發或者條件不滿足。

5. 回調函數應用

(1)同步中的回調

callback 不一定用於異步,一般同步(阻塞)的場景下也經常用到回調,比如要求執行某些操作後執行回調函數。

同步(阻塞)中使用回調的例子:

var func1=function(callback){
    //do something...(同步任務)
    (callback && typeof(callback) === "function") && callback();
}

var func2=function(){
/* 定義func2 */
	//do something...
}
func1(func2); //fun1執行完後執行fun2

(2)異步中的回調

異步回調的例子:

/* 定時器中使用回調,模擬異步 */
function callback(data){
	if(data.username === 'admin'){
		console.log('驗證成功');
	}
}
function fn(callback){
	setTimeout(function(){
		var obj = {
			username:'admin',
			password:123456
		}
		callback(obj)
	},1000)
}
fn(callback)  //=> 1s後,'驗證成功' 。

總結:

  • 資源加載:動態加載js文件後執行回調,加載iframe後執行回調,ajax操作回調,圖片加載完成執行回調,等異步操作。
  • 事件:DOM事件及Node.js事件基於回調機制 (Node.js回調可能會出現多層回調嵌套的問題)。
  • setTimeout的延遲時間爲0,這個hack經常被用到,settimeout調用的函數其實就是一個callback的體現
  • 鏈式調用:鏈式調用的時候,在賦值器(setter)方法中(或者本身沒有返回值的方法中)很容易實現鏈式調用,而取值器(getter)相對來說不好實現鏈式調用,因爲你需要取值器返回你需要的數據而不是this指針,如果要實現鏈式方法,可以用回調函數來實現【不太能理解】
  • setTimeout、setInterval的函數調用得到其返回值。由於兩個函數都是異步的,即:他們的調用時序和程序的主流程是相對獨立的,所以沒有辦法在主體裏面等待它們的返回值,它們被打開的時候程序也不會停下來等待,否則也就失去了setTimeout及setInterval的意義了,所以用return已經沒有意義,只能使用callback。【不太理解】callback的意義在於將timer執行的結果通知給代理函數進行及時處理。

二、Ajax

前言

下載 wampserverapache 服務器。
下載 postman 請求抓包工具

安裝方法:
參考:https://blog.csdn.net/qq_34195507/article/details/94851028
參考:https://blog.csdn.net/weixin_43738701/article/details/86607148

Ajax 概述

1. 什麼是 Ajax

Ajax中的第一個A是Asynchronous [eɪˈsɪŋkrənəs]
(異步)JavaScript and XML的縮寫。可以看出它不是一種技術,而是多種技術的綜合體。
其中有JavaScript、有xml、有json、有html、有css、有dom、有XMLHttpRequest對象等等。
XMLHttpRequest對象,也叫做Ajax對象,瀏覽器中自帶的對象。
Ajax的工作也是基於http協議的,用於傳輸。

2. Ajax 能做什麼

  • 從服務器中加載資源、上傳資源到服務器。
  • 提高用戶的體驗。
  • 表單的驗證。
  • 引入百度地圖、谷歌地圖。
  • 網頁版的聊天室。
  • 無刷新分頁。

3. Ajax 工作原理

在這裏插入圖片描述
1)創建Ajax 對象 var xhr = new XMLHttpRequest();
2)準備發送資源以及發送地址,請求方式,確定同步發送還是異步發送。
3)調用open() 方法對資源進行發送xhr.open('請求方法','請求地址',同步或異步)
4)監聽服務器返回的結果xhr.onreadystatechange = function(){/* 監聽函數 */}
5)發送請求,調用Ajax 對象的send() 方法。xhr.send()

4. 主要成員屬性以及方法

屬性:

  • readyState:表示xhr 工作到何種情況。
  • onreadystatechange:事件,表示 readyState 改變時觸發的事件。
  • status:http 狀態碼。
  • responseText:用來接收返回的文本類型的數據
  • responseXML:用來接收返回的是XML格式的數據

方法:

  • open():設置(定義)一個請求,比如(get請求、post請求…)
  • send():發送設置好的請求,還可以用來發送請求資源。
  • setRequestHeader():設置ajax請求頭信息

5. Ajax 的基本使用

完成驗證用戶名案例,要求用戶名唯一,就是不能有重複。
頁面中有一個文本框,當失去焦點的時候,驗證輸出的內容是否已經存在。
HTML

<input type="text" name="username" id="username"> <span id="msg"></span>

JS

/* GET請求 */
document.getElementById('username').onblur = function(){
	/* 1.創建Ajax 對象實例 */
	var xhr = new XMLHttpRequest();
	/* 2.準備發送資源 */
	var uname = this.value;
	/* 3. 備發送資源以及發送地址,請求方式,確定同步發送還是異步發送*/
	/* 注意:發送get請求,資源寫在請求路徑上以 ?連接 */
	xhr.open('get','checkusername.php?u='+uname,true);
	/* 4.發送請求 */
	xhr.send();
	/* 5.監聽服務器返回的結果 */
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4&& xhr.status == 200){
			/* 處理返回的結果 */
			var res = xhr.responseText;
			if(res == 1){
				document.getElementById('msg').innerHTML = '<font color="red">sorry,用戶名已存在</font>'
			}else{
				document.getElementById('msg').innerHTML = '<font color="green">恭喜用戶成功</font>'
			}
		}
	}
}

PHP

/* checkusername.php */
/* 後臺服務器進行邏輯判斷 */
<?php
$arr = ['zhangsan','lishi','wangwu'];
$u = $_GET['u'];
if(in_array($u,$arr)){
	echo 1;
}else{
	echo 0;
}
>

注意點:

  • 用get方式請求,所以參數直接寫到url上即可。服務器端獲取地址欄的參數,同樣使用$_GET來獲取。
  • 接受服務器返回的數據時要對Ajax進程進行監聽。

如果沒有進行Ajax 進程監聽,無法得到服務器返回的數據。

/* GET請求 */
document.getElementById('username').onblur = function(){
	var xhr = new XMLHttpRequest();
	var uname = this.value;
	xhr.open('get','checkusername.php?u='+uname,true);
	xhr.send();
	var res = xhr.responeText;
	console.log(res);          //=>  無法獲取返回數據
		if(res == 1){
			document.getElementById('msg').innerHTML = '<font color="red">sorry,用戶名已存在</font>'
		}else{
			document.getElementById('msg').innerHTML = '<font color="green">恭喜用戶成功</font>'
		}
	}

原因就是因爲Ajax 請求存在過程問題,由於send()後數據進行傳輸,如果傳輸數據過大需要的時間就越長,而JavaScript並不會等待有數據了它才返回(異步問題)。所以需要監聽Ajax 進程,當Ajax 進程發生改變就調用事件,當 readyState==4時表示數據接收完畢可以通過某些方法屬性返回數據了。
在這裏插入圖片描述

6. 細節問題

(1)對字符進行編碼

默認情況下傳輸數據是什麼,url 上的地址拼接就是什麼。
例如上代碼的輸出:
在這裏插入圖片描述
解決的辦法就是對用戶輸入的內容進行編碼。

  • encodeURI() — 不能對“:/=&”進行編碼,能對漢字進行編碼
  • encodeURIComponent() — 能對“:/=&”進行編碼,也能對漢字進行編碼

在這裏插入圖片描述
一般情況下,JS編碼後發送到服務器,PHP會自動解碼,如果沒有自動解碼,用PHP的函數urldecode來解碼。

(2)緩存處理

什麼是Ajax緩存原理?
Ajax在發送的數據成功後,會把請求的URL和返回的響應結果保存在瀏覽器緩存內,當下一次調用Ajax發送相同的請求時,它會直接從緩存中把數據取出來,這是爲了提高頁面的響應速度和用戶體驗。當前這兩次請求URL完全相同,包括參數。這個時候,瀏覽器就不會與服務器交互。
兩次請求的地址完全一致(包括參數),那麼IE就會從緩存中取服務器上一次返回的結果。而不會從新向服務器發送請求。

在這裏插入圖片描述
如何解決IE緩存的問題:

  1. 在ajax對象.send()前加上 xhr.setRequestHeader("If-Modified-Since","0"); //實測可用
  2. 在服務器端加
    header("Cache-Control:no-cache");
    header("Pragma:no-cache");
    header("Expires:-1");
    加入三個header,目的是讓所有的瀏覽器都不緩存。
  3. Ajax 的 URL 參數後加上 "?fresh=" + Math.random()//當然這裏參數 fresh 可以任意取了
  4. 第種方法和第3種類似,在 URL 參數後加上 "?timestamp=" + new Date().getTime()
  5. 使用POST 請求替代GET 請求。

7. Ajax 中使用GET請求與POST請求的區別

在這裏插入圖片描述
請求寫法上的區別:

區別一:請求方式不同。
區別二:GET請求將傳遞參數寫在請求地址中(與地址拼接),POST請求則將參數放入send()中進行發送。
區別三:POST 請求需要設置請求頭。
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
區別四:服務器端用$_GET對GET請求參數進行獲取,使用$_POST對POST請求參數進行獲取。

本質區別:

參考博客:https://blog.csdn.net/Errrl/article/details/103467472

對ajax中的get和post的一些說明:

①、用post請求,不會產生緩存。
②、用post請求的時候,能不能也用get,即post和get請求同時使用。答案是能,只不過get請求的參數用$_GET獲取,post請求的參數用$_POST獲取。
③、用$_REQUEST獲取get和post方式提交的參數,如果參數名相同,獲取的是誰?獲取的是post的內容。

8. Ajax 中的同步與異步說明

同步請求,在同一個時間點上,只能有一個進程;其他進程只能等待。
異步請求,在同一個時間點上,可以同時進行多個進程。
open方法的第三個參數表示同步或者是異步請求。默認值true表示異步請求,false表示同步請求。
在這裏插入圖片描述

發佈了37 篇原創文章 · 獲贊 6 · 訪問量 2212
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章