1. 程式人生 > >ES7之async的理解

ES7之async的理解

本章介紹 Brian Terlson 提議的 ECMAScript 2017 新特性 Async Functions(非同步函式) 。

概述

async(非同步) 函式變體

以下是已經存在的非同步函式變體。請注意無處不在的 async 關鍵字。

  • 非同步函式宣告: async function foo() {}
  • 非同步函式表示式: const foo = async function () {};
  • 非同步函式定義:let obj = { async foo() {} }
  • 非同步箭頭函式: const foo = async () => {};

async(非同步) 函式總是返回 Promises

async(非同步) 函式的 Promise 完成狀態:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. return123;
  3. }
  4. asyncFunc()
  5. .then(x => console.log(x));
  6. // 123

async(非同步) 函式的 Promise 拒絕狀態:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. thrownewError('Problem!');
  3. }
  4. asyncFunc()
  5. .catch(err => console.log(err));
  6. // Error: Problem!

通過 await 處理 async(非同步) 計算的結果和錯誤

await(只允許在 async(非同步) 函式內部使用)等待其操作物件 Promise 返回:

  • 如果 Promise 是完成狀態,await 的結果是完成態的值。
  • 如果 Promise 是拒絕狀態,await 會丟擲拒絕值。

處理單個 async(非同步) 返回值:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const result = await otherAsyncFunc();
  3. console.log(result);
  4. }
  5. // 等價於:
  6. function asyncFunc(){
  7. return otherAsyncFunc()
  8. .then(
    result =>{
  9. console.log(result);
  10. });
  11. }

按順序處理多個 async(非同步) 返回值:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const result1 = await otherAsyncFunc1();
  3. console.log(result1);
  4. const result2 = await otherAsyncFunc2();
  5. console.log(result2);
  6. }
  7. // 等價於:
  8. function asyncFunc(){
  9. return otherAsyncFunc1()
  10. .then(result1 =>{
  11. console.log(result1);
  12. return otherAsyncFunc2();
  13. })
  14. .then(result2 =>{
  15. console.log(result2);
  16. });
  17. }

並行處理多個 async(非同步) 返回值:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const[result1, result2]= await Promise.all([
  3. otherAsyncFunc1(),
  4. otherAsyncFunc2(),
  5. ]);
  6. console.log(result1, result2);
  7. }
  8. // 等價於:
  9. function asyncFunc(){
  10. returnPromise.all([
  11. otherAsyncFunc1(),
  12. otherAsyncFunc2(),
  13. ])
  14. .then([result1, result2]=>{
  15. console.log(result1, result2);
  16. });
  17. }

錯誤處理:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. try{
  3. await otherAsyncFunc();
  4. }catch(err){
  5. console.error(err);
  6. }
  7. }
  8. // 等價於:
  9. function asyncFunc(){
  10. return otherAsyncFunc()
  11. .catch(err =>{
  12. console.error(err);
  13. });
  14. }

理解 async(非同步) 函式

在我解釋 async(非同步) 函式之前,我需要解釋一下如何組合使用 Promises 和 Generator ,通過看起來同步的程式碼來執行 async(非同步) 操作。

對於能夠 async(非同步) 計算其一次性結果的函式,作為 ES6 一部分的 Promises 已經變得流行起來。一個例子是 客戶端 fetch API ,它是 XMLHttpRequest 獲取資料的替代方法。使用示例如下:

JavaScript程式碼:
  1. function fetchJson(url){
  2. return fetch(url)
  3. .then(request => request.text())
  4. .then(text =>{
  5. return JSON.parse(text);
  6. })
  7. .catch(error =>{
  8. console.log(`ERROR: ${error.stack}`);
  9. });
  10. }
  11. fetchJson('http://example.com/some_file.json')
  12. .then(obj => console.log(obj));

通過 generator 來編寫非同步程式碼

co 是一個使用 Promise 和 generator 來實現看似同步編碼的庫,但與上一示例中使用的樣式相同:

JavaScript程式碼:
  1. const fetchJson = co.wrap(function*(url){
  2. try{
  3. let request = yield fetch(url);
  4. let text = yield request.text();
  5. return JSON.parse(text);
  6. }
  7. catch(error){
  8. console.log(`ERROR: ${error.stack}`);
  9. }
  10. });

每次回撥函式( generator 函式)產生一個 Promise 物件給 co ,回撥會被暫停,只有當 Promise 執行完成後,co 才會繼續執行回撥 。 如果 Promise 處於完成狀態,yield 返回完成狀態的值,如果處於拒絕狀態,yield 丟擲拒絕狀態的錯誤。此外,co 保證結果是通過回撥執行完成才返回的(類似於 then() 所做的工作)。

通過 async(非同步) 函式來編寫非同步程式碼

async(非同步) 函式用的特定語法基本上和 co 類似:

JavaScript程式碼:
  1. async function fetchJson(url){
  2. try{
  3. let request = await fetch(url);
  4. let text = await request.text();
  5. return JSON.parse(text);
  6. }
  7. catch(error){
  8. console.log(`ERROR: ${error.stack}`);
  9. }
  10. }

在內部,非同步函式寫法更類似於 generators 。

以同步開始,非同步處理的 async(非同步) 函式

以下是 async(非同步)函式是如何工作的:

  1. async(非同步) 函式總是返回一個 Promise 物件 p 。Promise 物件在 async(非同步) 函式開始執行時被建立。
  2. 函式體執行過程中,可以通過 return 或 throw 終止執行。或者通過 await 暫停執行,在這種情況下,通常會在以後繼續執行。
  3. 返回 Promise 物件 p

當執行 async(非同步) 函式的函式體時,return x 中的 x 是 Promise 物件 p 的完成狀態的結果,而 throw err 是 p 的拒絕狀態的結果。執行結果是非同步返回的。換句話說:then() 和 catch() 的回撥總是在當前程式碼完成後執行。

以下是程式碼示例:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. console.log('asyncFunc()');// (A)
  3. return'abc';
  4. }
  5. asyncFunc().
  6. then(x => console.log(`Resolved: ${x}`));// (B)
  7. console.log('main');// (C)
  8. // Output:
  9. // asyncFunc()
  10. // main
  11. // Resolved: abc

您可以認為是以下的執行順序:

  1. 行A:async(非同步) 函式以同步開始。async(非同步) 函式的 Promise 通過 return 來返回完成狀態的結果。
  2. 行C:執行繼續。
  3. 行B:Promise 完成狀態通知是非同步發生的。

返回不被包裹的 Promise 物件

Promise 的 resolve 是一項標準操作。 return 就是使用它來 resolve async(非同步) 函式的 Promise p 的。這意味著:

  1. 返回一個非 Promise 值,該值將被處理成 p 的完成狀態值。
  2. 返回一個 Promise 物件,那麼 p 此時相當於是該 Promise 的狀態。

因此,您可以返回一個 Promise ,並且這個 Promise 不會包裹在別的 Promise 中:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. returnPromise.resolve(123);
  3. }
  4. asyncFunc()
  5. .then(x => console.log(x))// 123

有趣的是,返回一個拒絕狀態(reject)的 Promise 物件會導致 async(非同步) 函式被拒絕(reject)(通常,您可以使用 throw ):

JavaScript程式碼:
  1. async function asyncFunc(){
  2. returnPromise.reject(newError('Problem!'));
  3. }
  4. asyncFunc()
  5. .catch(err => console.error(err));// Error: Problem!

這與 Promise 解決方案的工作方式是一致的。 使你能夠在不使用 await 的情況下,使用其他 async(非同步) 計算來執行完成和拒絕處理:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. return anotherAsyncFunc();
  3. }

上面的程式碼示例和下面的類似,但是比下面的更高效。(以下程式碼示例沒有包裹 anotherAsyncFunc() 的 Promise ,而是包裹 anotherAsyncFunc() 本身 ):

JavaScript程式碼:
  1. async function asyncFunc(){
  2. return await anotherAsyncFunc();
  3. }

使用 await 小貼士

不要忘記使用 await

在 async(非同步) 函式中容易犯的一個錯誤就是在呼叫 async(非同步) 函式時忘記使用 await :

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const value = otherAsyncFunc();// missing `await`!
  3. ···
  4. }

在這個例子中,方法執行返回的 Promise 物件賦值給了 value ,它通常不是你在 async(非同步) 函式中想要的結果。

await 甚至可以在 async(非同步) 函式不返回任何值的情況下起作用。它的 Promise 只是用來告訴呼叫者完成狀態。例如:

JavaScript程式碼:
  1. async function foo(){
  2. await step1();// (A)
  3. ···
  4. }

行A中的 await 確保在執行 foo() 剩餘部分之前, step1() 已經執行完成。

不需要使用 await 的情況

有時,你只想觸發非同步計算,並且不需要關注它什麼時候完成。以下是程式碼示例:

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const writer = openFile('someFile.txt');
  3. writer.write('hello');// don’t wait
  4. writer.write('world');// don’t wait
  5. await writer.close();// wait for file to close
  6. }

在這裡,我們不關心單個的寫入操作是否完成,只需要他們以正確的順序執行 (API必須保證,但這是由 async(非同步) 函式的執行模型所鼓勵的,正如我們所見)。

asyncFunc() 函式最後一行的 await 確保該函式僅在檔案寫入關閉後才會執行。

由於返回的 Promises 沒有被其他 async(非同步) 函式包裹,所以你可以用 return 替換 await writer.close() :

JavaScript程式碼:
  1. async function asyncFunc(){
  2. const writer = openFile('someFile.txt');
  3. writer.write('hello');
  4. writer.write('world');
  5. return writer.close();
  6. }

這兩個版本各有利弊,await 版本可能稍微更容易理解。

await 是順序執行的,Promise.all() 是並行的

下面的程式碼呼叫了兩個 async(非同步) 函式, asyncFunc1() 和 asyncFunc1() 。

JavaScript程式碼:
  1. async function foo(){
  2. const result1 = await asyncFunc1();
  3. const result2 = await asyncFunc2();
  4. }

這兩個函式呼叫順序執行。但是並行執行它們往往會加快速度。您可以使用 Promise.all() :

JavaScript程式碼:
  1. async function foo(){
  2. const[result1, result2]= await Promise.all([
  3. asyncFunc1(),
  4. asyncFunc2(),
  5. ]);
  6. }

我們現在正在等待一個包含兩個元素的陣列的 Promise ,而不是等待兩個 Promise。

非同步函式和回撥

async(非同步) 函式的一個限制是 await(等待) 隻影響直接相關的 async(非同步) 函式。因此,async(非同步) 函式無法在回撥(但是,回撥可以是 async(非同步) 函式本身,稍後我們將會看到)中使用 await(等待)。這使得基於回撥的實用函式和方法難以使用。例子中我們將使用陣列方法 map() 和 forEach()

Array.prototype.map()

我們從陣列方法 map() 開始講解。在下面的程式碼示例中,我們想要載入由 URLs 陣列指向的檔案,並將它們返回到陣列中。

JavaScript程式碼:
  1. async function downloadContent(urls){
  2. return urls.map(url =>{
  3. // 錯誤的語法!
  4. const content = await httpGet(url);
  5. return content;
  6. });
  7. }

這不起作用,因為在正常箭頭函式中 await 語法上是非法的(愚人碼頭注: await(等待) 隻影響直接相關的 async(非同步) 函式)。那麼如何使用非同步的箭頭函式呢?

JavaScript程式碼:
  1. async function downloadContent(urls){
  2. return urls.map(async (url)=>{// 注意這一行中的 async ;
  3. const content = await httpGet(url);
  4. return content;
  5. });
  6. }

這段程式碼有兩個問題:

  • 現在返回的結果是一個 Promises 物件的陣列,而不是一個字串的陣列。
  • 一旦 map() 執行完成,回撥執行的工作並不能同時完成,因為 await 只暫停了包裹它的箭頭函式 和 httpGet() 非同步執行達到完成狀態。這意味著你不能使用 await,來等待 downloadContent() 執行結束。

我們可以通過 Promise.all() 來解決這兩個問題,Promise.all() 可以將一系列的 Promise 轉換為一個 Promise 陣列(所有值都是經過 Promise 完成並返回):

JavaScript程式碼:
  1. async function downloadContent(urls){
  2. const promiseArray = urls.map(async (url)=>{
  3. const content = await httpGet(url);
  4. return content;
  5. });
  6. return await Promise.all(promiseArray);
  7. }

map() 的回撥並不對 httpGet() 的結果起作用,只是起到不斷執行的作用。因此,這裡我們不需要一個非同步的箭頭函式,只需要一個普通的箭頭函式就能達到相同的結果。

JavaScript程式碼:
  1. async function downloadContent(urls){
  2. const promiseArray = urls.map(
  3. url => httpGet(url));
  4. return await Promise.all(promiseArray);
  5. }

我們仍然可以做一個小的改進:這個非同步函式稍微有點低效 – 首先通過 await 來解開 Promise.all() 的結果,然後通過 return 再次包裹它。 假設 return 不包裹 Promises,我們可以直接返回 Promise.all() 的結果:

JavaScript程式碼:
  1. async function downloadContent(urls){
  2. const promiseArray = urls.map(
  3. url => httpGet(url));
  4. returnPromise.all(promiseArray);
  5. }

Array.prototype.forEach()

我們使用陣列的 forEach() 方法在控制檯中列印幾個通過 URLs 載入的檔案的內容:

JavaScript程式碼:
  1. async function logContent(urls){
  2. urls.forEach(url =>{
  3. // Wrong syntax
  4. const content = await httpGet(url);
  5. console.log(content);
  6. });
  7. }

同樣的,這裡的程式碼會產生一個語法錯誤,因為你不能在通常的箭頭函式內部使用 await 。

我們換作非同步箭頭函式:

JavaScript程式碼:
  1. async function logContent(urls){
  2. urls.forEach(async url =>{
  3. const content = await httpGet(url);
  4. console.log(content);
  5. });
  6. // Not finished here
  7. }

這段程式碼起作用了,但是會出現一個警告:httpGet() 返回的 Promise 物件是非同步完成的,這也意味著當 forEach() 返回的時候回撥可能還沒有結束,因此你無法等到 logContent() 只能結束。

如果你並不想要這個結果,你可以將 forEach() 轉換為 for-of 迴圈。

JavaScript程式碼:
  1. async function logContent(urls){
  2. for(const url of urls){
  3. const content = await httpGet(url);
  4. console.log(content);
  5. }
  6. }

現在一切都在 for-of 迴圈完成後完成。但是,處理步驟依次發生:httpGet() 只是在第一次呼叫完成後再次呼叫。如果您希望處理步驟並行執行,你必須使用 Promise.all()

JavaScript程式碼:
  1. async function logContent(urls){
  2. await Promise.all(urls.map(
  3. async url =>{
  4. const content = await httpGet(url);
  5. console.log(content);
  6. }));
  7. }

map() 用於建立一個 Promises 陣列。 我們對他們的完成結果並不感興趣,我們只要 await(等待) 所有方法執行完成。這意味著我們希望的是在 async(非同步) 函式完成之後所有的執行都已經完成。我們也可以返回 Promise.all() ,但是該函式的結果是一個數組,其元素都是未完成狀態的。

使用非同步函式小貼士

瞭解你的 Promises

async(非同步) 函式的基礎就是 Promises 物件,這就是為什麼理解 Promises 對於理解 async(非同步) 函式至關重要。特別是當遇到不是基於 Promises 的老程式碼來實現 async(非同步) 函式時,你通常別無選擇,只能用 Promise 來重構。

舉個例子,這裡有個 “promisified” 版本的 XMLHttpRequest :

JavaScript程式碼:
  1. function httpGet(url, responseType=""){
  2. returnnewPromise(
  3. function(resolve, reject){
  4. const request =newXMLHttpRequest();
  5. request.onload =function(){
  6. if(this.status ===200){
  7. // Success
  8. resolve(this.response);
  9. }else{
  10. // Something went wrong (404 etc.)
  11. reject(newError(this.statusText));
  12. }
  13. };
  14. request.onerror =function(){
  15. reject(newError(
  16. 'XMLHttpRequest Error: '+this.statusText));
  17. };
  18. request.open('GET', url);
  19. xhr.responseType = responseType;
  20. request.send();
  21. });
  22. }

XMLHttpRequest 的 API 是基於回撥的。通過一個 async(非同步) 函式來實現它,意味著你必須在回撥中返回 Promise 的完成(fulfill) 或拒絕(reject) 狀態。這是不可能的,因為你只能通過 return 或者 throw 來完成這樣的操作。你不能從回撥函式內部 return 一個函式的結果。throw也有類似的約束。

因此,非同步函式的通用編碼風格是:

  • 直接使用 Promise 物件來構建非同步原語。
  • 用非同步函式來使用這些原語。

擴充套件閱讀:“Exploring ES6” 中的 “非同步程式設計中的 Promises 物件” 章節

立即呼叫非同步函式表示式

有時,如果你可以在模組或指令碼的頂層使用 await ,那將是一種很好的選擇。當然,它只能在非同步函式中使用。您可以建立一個非同步函式 main()  並立即呼叫它:

JavaScript程式碼:
  1. async function main(){
  2. console.log(await asyncFunction());
  3. }
  4. main();

或者您可以使用立即呼叫非同步函式表示式:

JavaScript程式碼:
  1. (async function(){
  2. console.log(await asyncFunction());
  3. })();

另一個選擇是立即呼叫非同步箭頭函式:

JavaScript程式碼:
  1. (async ()=>{
  2. console.log(await asyncFunction());
  3. })();

用非同步函式進行單元測試

以下程式碼使用 測試框架 mocha 對非同步函式 asyncFun1() 和 asyncFun2() 來進行單元測試:

JavaScript程式碼:
  1. import assert from 'assert';
  2. // Bug: the following test always succeeds
  3. test('Testing async code',function(){
  4. asyncFunc1()// (A)
  5. .then(result1 =>{
  6. assert.strictEqual(result1,'a');// (B)
  7. return asyncFunc2();
  8. })
  9. .then(result2 =>{
  10. assert.strictEqual(result2,'b');// (C)
  11. });
  12. });

然而,這個測試總是成功的,因為 mocha 不會等待 B 行和 C 行斷言執行完成。

你可以通過返回鏈式呼叫的 Promise 來解決這個問題,因為 mocha 會識別一個測試是否返回一個 Promise ,然後等待該 Promise 完成 再進行下一步(除非超時)。

JavaScript程式碼:
  1. return asyncFunc1()// (A)

非同步函式總是返回 Promises ,這使得它們能方便的、完美的來進行這種單元測試:

JavaScript程式碼:
  1. import assert from 'assert';
  2. test('Testing async code', async function(){
  3. const result1 = await asyncFunc1();
  4. assert.strictEqual(result1,'a');
  5. const result2 = await asyncFunc2();
  6. assert.strictEqual(result2,'b');
  7. });

在 mocha 中使用非同步單元測試非同步函式有兩個優點:程式碼更簡潔,能夠準確處理返回的 Promise 物件。

不要擔心沒有處理的拒絕拒態

當前的 JavaScript 引擎可以在拒絕態未處理的情況下提出警告。以下程式碼在過去會經常執行失敗,但是當前的 JavaScript 引擎可以進行警告:

JavaScript程式碼:
  1. async function foo(){
  2. thrownewError('Problem!');
  3. }
  4. foo();

閱讀延伸

相關推薦

ES7async理解

本章介紹 Brian Terlson 提議的 ECMAScript 2017 新特性 Async Functions(非同步函式) 。 概述 async(非同步) 函式變體 以下是已經存在的非同步函式變體。請注意無處不在的 async 關鍵字。 非同步函式宣告: async function

ES7async/await 同步還是非同步

async/await作為ES7的標準被視作javascript非同步函式操作的終極解決方案(超越Promise和Generator)越來越受到重視,而隨著前端構建工具的蓬勃發展,通過配置babel我們在專案中也可以直接使用這一新特性而無需太過在意瀏覽器的相容性

ES6或ES7async函式的用法,通過一段程式碼理解它的用法

ES6或ES7 中async函式的用法,一行一行看完程式碼和後面的解釋,應該就會用了吧 首先,如果不懂Promise的用法,那可能你看不懂這裡寫的async的用法。 上面是async使用例子,async是非同步操作的新方案,asyncPrint函式中第21行的

理解koa2 async + await + promise

koa是下一代的Node.js web框架。 我們首先使用koa來實現一個簡單的hello world吧!假如目前的專案結構如下: ### 目錄結構如下: koa-demo1 # 工程名 | |--- app.js

簡談對ES7async和await的理解

如果遇到過深度回撥的朋友一定對JS的回撥地獄再熟悉不過了,舉個例子說(如果我的列子不恰當盡請諒解),常見的就是省市區級聯吧,假如我要獲取一個縣級市的資訊,那麼我首先得獲得它所在的省的資訊,當取得省的資訊以後,再拉去地級市的資訊,當獲得地級市的資訊以後,然後才有可能獲取到它的資

謝煙客---------Linux深入理解anaconda使用

linux獲取詳細的幫助: 官方文檔: 《Installation Guide》anaconda位置anaconda命令行anaconda配置方式kickstart文件格式kickstart創建基於光盤安裝linuxanaconda位置 光盤、ftp、nfs、httpd、nfs**基於光盤,安裝l

Vue徹底理解自定義組件的v-model

自動 value tro 需要 this 變量 mode type 自定義 最近在學習vue,今天看到自定義事件的表單輸入組件,糾結了一會會然後恍然大悟...官方教程寫得不是很詳細,所以我決定總結一下。 v-model語法糖 v-model實現了表單輸入的雙向綁定,我們

Android開發深入理解泛型extends和super的區別

我想 lis dataset 文檔 cnblogs extend 擦除 選擇 提前 摘要: 什麽是泛型?什麽是擦除邊界?什麽是上界限定或下界限定(子類型限定或超類型限定)?什麽是類型安全?泛型extends關和super關鍵字結合通配符?使用的區別,兩種泛型在實際Andro

css深入理解overflow

com bsp mage overflow log clas 自己 blog info 主要是對大神講解的視頻的總結,我自己是寫不出來什麽東東的 css之深入理解overflow

生產者/消費者模式深入理解

模板 必須 winapi 協議 針對 sso 額外 fill 功能實現 #include <windows.h> #include <iostream> const unsigned short SIZE_OF_BUFFER = 2; //緩沖區長

Java動態代理通俗理解

java動態代理代理模式介紹 代理模式是一種常用的設計模式,其作用就是為目標對象提供額外的訪問方式,在不修改目標對象的前提下,擴展目標對象的額外功能,比如統計執行時間,打印日誌等。 代理模式分為兩種:靜態代理和動態代理。 需求:假如不想改動原有代碼情況下,並記錄用戶保存方法的執行時間。示例代碼如下: 接口 p

Linux SSH 理解

SSHSSH 理解 一、服務端sshd_conf配置文件理解 Port 22 #ssh 連接默認端口 PermitRootLogin yes #是否允許root用

區塊鏈TOP1重入漏洞自我理解【原創】

bubuko ont 國內 編程語言 credit 導致 被攻擊 復合 我們 最近在研究區塊鏈方面的漏洞,智能合約top 1重入漏洞。在網上找了很多相關的文章,發現大部分都是通過代碼進行分析。話說,我們不了解平臺,只是熟悉代碼,只知其原理不知其過程,不便於我們的漏洞理解。

Java多線程深入理解synchronize關鍵字

tracking 而不是 方法 獲得 content cal art track () synchronize鎖重入: 關鍵字synchronize擁有鎖重入的功能,也就是在使用synchronize時,當一個線程的得到了一個對象的鎖後,再次請求此對象是可以再次得到

ES6知識點整理----async----語法

整理 pro 指定 bsp fun clas 參數 function resolve 1、async函數返回一個 Promise 對象。 2、async函數內部return語句返回的值,會成為then方法回調函數的參數。 async function f() { re

js 難點原型理解

意圖 使用 指向 const ant 區別 ott 調用 images 構造函數創建對象我們先使用構造函數創建一個對象:function Person() { } var person = new Person(); person.name = ‘Kevin‘; conso

*bin理解

ber 記錄 link padding 如果 http 出了 a star usr 在程序運行中,使用bins結構對釋放的堆塊進行管理,以減少向系統申請內存的開銷,提高效率。 chunk數據結構 從內存申請的所有堆塊,都使用相同的數據結構——malloc_chunk,但在i

C語言自學指標理解

目的: 通過以下學習,希望能理解指標的概念,理解指標和陣列的關係,理解指標的定義,掌握指標的用法。 1. 簡述   用C語言寫的程式碼基本上都用到指標,掌握好指標的概念對學好C有很大幫助。 為了方便理解我們可以把指

UGUI Canvas理解

對於UGUI來說,Canvas這個元件至關重要,由於自己對UGUI也是初學者,根據使用過程中的理解做一下總結; Canvas (畫布) 是所有 UI 元件的父物體 , 也就是說每一個 UI 元件都必須在 Canvas 下 , 作為 Canvas 的子物體 , 當你建立一個 UI 控制元件時

影象學習如何理解方向梯度直方圖(Histogram Of Gradient)

按:本文作者 Slyne_D,原文載於作者的簡書主頁,用於非商業學習,侵刪致歉! 本文主要翻譯了Histogram of Oriented Gradients一文。 特徵描述子(Feature Descriptor) 特徵描述子就是影象的表示,抽取了有用的資訊,丟掉了