fetch是用來取代傳統的XMLHttpRequest的。 它的優勢不少,包括鏈式調用的語法、返回promise等。前端
fetch api是基於promise的設計,它是爲了取代傳統xhr的不合理的寫法而生的。node
xhr請求寫起來很是的混亂,以下所示:git
var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'json'; xhr.onload = function() { console.log(xhr.response); }; xhr.onerror = function() { console.log("Oops, error"); }; xhr.send();
可是使用fetch以後,以下所示:github
fetch(url).then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops, error"); });
這種鏈式調用的風格看上去會很是舒服。ajax
若是咱們再使用了箭頭函數就會更加簡潔了。 數據庫
fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
經過使用fetch api,能夠將傳統的xhr的粗糙的使用方法轉化的如此精簡,實在是好! json
可是呢? 使用Promise,仍是能夠很明顯看到callback的使用,不急,咱們還能夠使用 async、await :api
// Async/Await requirements: Latest Chrome/FF browser or Babel: https://babeljs.io/docs/plugins/transform-async-to-generator/ // Fetch requirements: Latest Chrome/FF browser or Github fetch polyfill: https://github.com/github/fetch // async function async function fetchAsync () { // await response of fetch call let response = await fetch('https://api.github.com'); // only proceed once promise is resolved let data = await response.json(); // only proceed once second promise is resolved return data; } // trigger async function // log response or catch error of fetch promise fetchAsync() .then(data => console.log(data)) .catch(reason => console.log(reason.message))
這樣看上去是否是就好多了呢?跨域
注意: 對於async和await的使用仍是很明確的,就是通常咱們在一個異步函數以前添加 await 關鍵詞,而後在這個 await 的相關代碼外面使用的時 async 函數,這樣的結合纔是合適的。promise
利用 async 和 await,咱們就能夠像寫同步代碼同樣來寫異步代碼啦!
可是呢,目前async 和 await 的支持性還不是很好,目前還沒法在通常的瀏覽器中使用!
fetch必須接受一個資源路徑做爲參數,而且返回了一個promise,因此咱們能夠直接使用鏈式調用的方式。
fetch("/getAllProduct").then(function(res) { return res.json(); }).then(function (data) { if (data.code == 200) { console.log('獲取到全部產品' ,data.data); that.props.addAllProduct(data.data); } else { console.log(data.message); } })
這樣,咱們就能夠發送一個ajax請求。
/* 對客戶端的返回數據封裝 * @param [code] (number) code爲返回的狀態碼 * @param [message] (string) message爲返回的信息 * @param [data] (any) data是可選的,爲返回給前端的數據 */ // 注意: retrunJson中的res爲node處理接口的回調函數中的res,這個是必須的。 function returnJson(res, code, message, data) { var response = { code: code, message: message }; if (typeof data !== 'undefined') { response.data = data; } res.json(response);
// 返回這個請求以後,必需要 res.end()表示請求的結束,不然後臺可能會崩潰。 res.end(); } router.post('/register', function (req, res) { let userName = req.body.username, password = req.body.password, passwordAgain = req.body.passwordAgain, type = req.body.type; console.log(userName, password, type); if (type == 1) { if (password == passwordAgain) { let managerId = uuidv1(); console.log(userName, password, passwordAgain); var newUser = new Manager({ name: userName, password: password, type: req.body.type, managerId: managerId }); Manager.find(userName, function (err, user) { if (err) { returnJson(res, 5001, '服務器錯誤,註冊失敗'); } else { if (user !== null) { returnJson(res, 4003, "此用戶已經註冊!"); } else { // 若是符合條件,就註冊該用戶,將數據保存在數據庫。 newUser.save(function (err, user) { if (err) { // 服務器端錯誤,失敗返回狀態碼500 returnJson(res, 500, "用戶註冊失敗!"); } else { // user數據較簡單,直接傳遞user便可,若是複雜,咱們能夠考慮使用對象形式傳遞更多數據。 returnJson(res, 200, "用戶註冊成功!", user); } }); } } }); } else { returnJson(res, 4001, "用戶兩次輸入密碼不一致!"); } } else if( type == 2) { if (password == passwordAgain) { let userId = uuidv1(); console.log(userName, password, passwordAgain); var newUser = new User({ name: userName, password: password, type: req.body.type, userId: userId }); User.find(userName, function (err, user) { if (err) { returnJson(res, 5001, '服務器錯誤,註冊失敗'); } else { if (user !== null) { returnJson(res, 4003, "此用戶已經註冊!"); } else { // 若是符合條件,就註冊該用戶,將數據保存在數據庫。 newUser.save(function (err, user) { if (err) { // 服務器端錯誤,失敗返回狀態碼500 returnJson(res, 500, "用戶註冊失敗!"); } else { // user數據較簡單,直接傳遞user便可,若是複雜,咱們能夠考慮使用對象形式傳遞更多數據。 returnJson(res, 200, "用戶註冊成功!", user); } }); } } }); } else { returnJson(res, 4001, "用戶兩次輸入密碼不一致!"); } } });
這樣,咱們就能夠處理一個ajax請求。
一、fetch() 返回的是一個Promise對象。
fetch使用的promise對象能夠使得咱們使用同步的方式寫異步函數。
二、 fetch api是能夠結合 async 和 await 來使用的。
fetch是基於promise實現的,可是使用promise的寫法,咱們仍是能夠看到callback的影子,若是結合 async和await來使用,仍是很是不錯的。
三、 Fetch api 提供的spi囊括可是不限於xhr的全部功能。
四、 fetch api 能夠跨域。
參考: https://fetch.spec.whatwg.org/#http-cors-protocol
跨域請求必須包括 Origin 做爲header.
以上。
咱們在發送fetch請求的時候就會使用到CORS協議,儘管這些對於開發者來講是透明的,可是瀏覽器仍是會發送 origin 字段。
五、fetch提供了對request和response對象的通用定義。
Fetch 提供了對 Request 和 Response (以及其餘與網絡請求有關的)對象的通用定義。所以在一個Fetch請求中,徹底能夠只使用Request 和 Response兩個對象,經過Request 設置參數,經過Response 對返回值進行處理。
因此,咱們能夠將一個fetch定義以下:
var myHeaders = new Headers(); myHeaders.append('Content-Type', 'image/jpeg'); var option = { method: 'GET', headers: myHeaders, mode: 'cors', cache: 'default' }; var myRequest = new Request('https://api.github.com/users/mzabriskie',option); fetch(myRequest).then(function(response) { ... });
參考文章: https://github.com/camsong/blog/issues/2