js中回調函數(callback)的一些理解


前言

我個人在學習Node.js相關知識時遇到了回調函數這個概念,雖然之前已經在c,c++等編程語言中用到過它,但還一直未對其機制有深入了解,這次就來好好談一下它。

 

概念理解

百度對它的解釋是回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。

Google里的解釋是A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

字面上的理解,回調函數就是一個參數,將這個函數作為參數傳到另一個函數里面,當那個函數執行完之后,再執行傳進去的這個函數。這個過程就叫做回調。

這里我想把它通俗化來講,小時候大家應該都有自己喜歡看的動畫片,但是平時上學期間我們都會被家長“嚴格管制”。下午放學回家后,爸媽會讓自己先寫完作業才能看電視里放的動畫片。

其實這就是一個回調的過程。你建了個函數b(看動畫片),但前提是要寫完作業,寫作業的過程相當於執行函數a。在現實生活中你要寫完作業才能看動畫片,即在執行過程中需要等函數a執行完之后才能執行函數b。

不過必須清楚一點:函數b是以參數形式傳給函數a的,b是回調函數。

 

簡單的例子

function a(callback){ alert("這是first函數a"); var x =1; var y=2; return callback(x,y); } function b(x,y){ alert("這是回調函數b"); return x+y; } $(function(){ var result = a(b); alert("result = "+ result); });

輸出結果為:

這是first函數a

這是回調函數b

result = 3

這里函數首先執行了first函數a,之后調用了回調函數b,最后返回函數a的返回值。

 

回調函數的種類(按功能划分)

1.同步回調

它是一種阻塞式回調,比方說一段代碼邏輯沒有執行完畢,代碼會一直等待,而不會去執行下一段代碼邏輯。

2.異步回調

它是一種非阻塞式回調,比方說一段代碼邏輯沒有執行完畢,代碼執行可以不卡在這塊不動,而是可以去執行下一段代碼邏輯。

二者根本區別

在同步回調里,回調函數的調用一定發生在主函數返回之前。

在異步回調里,回調函數的調用有可能是在起始函數返回之后。

 

應用場景

回調函數應用場景多用在使用 js 寫組件時,尤其是組件的事件很多都需要回調函數的支持。

 

個人實例分享

前端登錄界面發送請求,后台Node.js連接數據庫實現登錄功能

html部分代碼:

<form action="#" id="form" name="form" method="post">
<div class="input_outer">
<span class="u_user"></span>
<input id="acnt" name="acnt" class="text" style="color:#FFFFFF !important;" type="text" placeholder="請輸入賬號">
</div>
<div class="input_outer">
<span class="us_uer"></span>
<input id="pswd" name="pswd" class="text" style="color:#FFFFFF !important;position: absolute; z-index: 100;" type="password" placeholder="請輸入密碼">
</div>
<div class="mb2">
<a class="act-but submit" style="color: #FFFFFF">登錄</a>
</div>
</form>

<script> $(function () { $(".act-but").on("click", function () { let acnt = $("#acnt").val(); let pswd = $("#pswd").val(); if (acnt && pswd){ $.post('login', { acnt: acnt, pswd: pswd }, function (data) { console.log(data); switch (data) { case '-1': alert("用戶不存在!"); break; case '0': alert("密碼錯誤!"); break; case '1': window.location.href='admin.html'; break; } } ); } else { alert("請輸入用戶名及密碼!"); } }); }) </script>

 

Node.js部分代碼:

var express = require('express'); var router = express.Router(); var bodyPaeser =require('body-parser'); var mysql=require('mysql'); var db=mysql.createConnection({ host:"localhost", user:"root", password:"123456", database: 'web' }); db.connect(function(err){ if(err){ console.log('[query] - :'+err); return; } console.log('mysql connection succeed'); } ); router.post('/login', function (req, res) { let acnt = req.body.acnt; let pswd = req.body.pswd; //let code = checkUser(acnt, pswd);
db.query('select user_name as user_name,password as password from user',function(err,rows) { if(err){ console.log('[query] - :'+err); return; } var x=-1; var i; var p=rows.length; for(i=0;i<p;i++) { if(acnt===rows[i].user_name) { if(pswd===rows[i].password) { x=1; yonghu=acnt; break; } else{ x=0; break; } } } res.writeHead(200, {"Access-Control-Allow-Origin": "http://localhost:63342"}); res.write(String(x)); res.end(); let state; switch (x) { case 1: state = " Success"; break; default: state = " Filed"; break; } console.log("User: " + acnt + " Pswd: " + pswd + state); }); });

 

這里前端通過表單提交信息給后台,后台Node.js對應的post函數中第二個參數就是一個回調函數,用於處理前后端交互。而在這個函數內部還存在一個連接數據庫的查詢函數,即db.query(),這里是因為事先引入了對應的連接mysql數據庫的模塊,所以在連接建立后可直接調用該模塊對應函數,重點是這個query函數,它的內部對應的第一個參數是數據庫查詢語句,第二個參數便又是一個回調函數,用於處理數據庫返回的結果。可見回調函數在Node.js實際開發過程中十分常見,並且有很多情況下是回調里面包含新的回調。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM