Node.js異步編程

1. 同步API,異步API

//路徑拼接
const public = path.join(_ dirname, 'public') ;  //經過返回值拿到
//請求地址解析
const url0bj = url. parse (req. ur1) ;   //經過返回值拿到
//讀取文件
fs. readFile(' ./demo.txt', 'utf8', (err, result) => {
console .1og (result) ;
}) ;    //經過函數方式拿到

同步API:只有當前API執行完成後,才能繼續執行下一個API編程

console.log('before') ;
console.log('after') ;

異步API:當前API的執行不會阻塞後續代碼的執行promise

console.log('before') ;
setTimeout (
() => { console.log('last');
},2000);
console.log('after');   //before after last

2. 同步API,異步API的區別(獲取返回值)

同步API能夠從返回值中拿到API執行的結果,可是異步API是不能夠的異步

//同步
function sum (n1, n2) {
return nl + n2;
}
const result = sum (10,20) ;
console.log(result);  //30
//異步
function getMsg () {
setTimeout (function () {
return {msg: 'Hello Node.js'}
},2000);
}
const msg = getMsg ();
console.log(msg)  //undefined

3. 回調函數

本身定義函數讓別人去調用。async

// getData函數定義
function getData (callback) {}
// getData函數調用
getData (() => {}) ;

4. 使用回調函數獲取異步API執行結果

function getMsg (callback) {
setTimeout (function () {
callback ({ msg:'Hel1o Node.js' })
},2000) ;
}
getMsg (function (msg) {
console.log (msg) ;
}) ;

5. 同步API,異步API的區別(代碼執行順序)

同步API從上到下依次執行,前面代碼會阻塞後面代碼的執行異步編程

for(vari=0;i<100000;i++){
console.log (i) ;
}
console.log('for循環後面的代碼) ;

異步API不會等待API執行完成後再向下執行代碼函數

console.log('代碼開始執行') ;
setTimeout(() => { console.1og('2秒後執行的代碼')},2000) ;
setTimeout(() => { console.log("0秒"後執行的代碼')},0) ;
console.log('代碼結束執行') ;

6. 代碼執行順序分析

console.log( '代碼開始執行') ;
setTimeout( () => {
console.log('2秒後執行的代碼') ;
},2000) ;
setTimeout( () = => {
console.log('"0秒"後執行的代碼') ;
},0);
console.log( '代碼結束執行') ;

 

 

7. Node.js中的異步API

fs. readFile('./demo.txt', (err, result) => {}) ;ui

var server = http. createServer() ; server.on(' request', (req, res) => {}) ;atom

若是異步API後面代碼的執行依賴當前異步API的執行結果,但實際上後續代碼在執行的時候異步API尚未 返回結果,這個問題要怎麼解決呢?url

fs. readFile(' ./demo. txt', (err, result) => {}) ; console. log('文件讀取結果') ;spa

需求:依次讀取A文件、B文件、C文件

//回調地域
const fs = require('fs');
fs.readFile('./01.js', 'utf-8', (err, doc) => {
   console.log(doc);
   fs.readFile('./02.js', 'utf-8', (err, doc) => {
       console.log(doc);
       fs.readFile('./03.js', 'utf-8', (err, doc) => {
           console.log(doc);
      });
  });
});

8. Promise

Promise出現的目的是解決Node.js異步編程中回調地獄的問題。

let promise = new Promise ((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve ({name: '張三' })
}else {
reject('失敗了')
},2000) ;
}) ;
promise.then (result => console.log (result); // {name: '張三 ' })
.catch(error => console.log(error); //失敗了)
const fs = require('fs');

function p1() {
   return new Promise((resolve, reject) => {
       fs.readFile('./01.js', 'utf-8', (err, result) => {
           resolve(result);
      });
  });
}

function p2() {
   return new Promise((resolve, reject) => {
       fs.readFile('./02.js', 'utf-8', (err, result) => {
           resolve(result);
      });
  });
}

function p3() {
   return new Promise((resolve, reject) => {
       fs.readFile('./03.js', 'utf-8', (err, result) => {
           resolve(result);
      });
  });
}
p1().then(result1 => {
   console.log(result1);
   return p2();
}).then(result2 => {
   console.log(result2);
   return p3();
}).then(result3 => {
   console.log(result3);
});

 

9. 異步函數

異步函數是異步編程語法的終極解決方案,它能夠讓咱們將異步代碼寫成同步的形式,讓代碼再也不有回調函數嵌套,使代碼變得清晰明瞭。

const fn = async () => {}; async function fn () {};

async關鍵字

  1. 普通函數定義前加async關鍵字 普通函數變成異步函數

  2. 異步函數默認返回promise對象

  3. 在異步函數內部使用return關鍵字進行結果返回 結果會被包裹的promise對象中 return關鍵字代替了resolve方法

  4. 在異步函數內部使用throw關鍵字拋出程序異常

  5. 調用異步函數再鏈式調用then方法獲取異步函數執行結果

  6. 調用異步函數再鏈式調用catch方法獲取異步函數執行的錯誤信息

await關鍵字

  1. await關鍵字只能出如今異步函數中

  2. await promise await後面只能寫promise對象,其餘類型的API是不能夠的

  3. await關鍵字是暫停異步函數向下執行,直到promise返回結果

// 在普通函數定義前加上async關鍵字, 普通函數就變成了異步函數
// 異步函數默認返回值是promise對象   Promise { undefined }
// throw 拋出異常
async function fn() {
   throw '發生了一些錯誤'; //throw以後的代碼不執行
   return 123;
}
fn().then(data => {
   console.log(data);
}).catch(err => {
   console.log(err);
});

async function p1() {
   return 'p1';
}
async function p2() {
   return 'p2';
}
async function p3() {
   return 'p3';
}
async function run() {
   let r1 = await p1();
   let r2 = await p2();
   let r3 = await p3();
   console.log(r1);
   console.log(r2);
   console.log(r3);
}
run(); //p1 p2 p3

解決Node.js異步編程中回調地獄的問題

const fs = require('fs');
// promisify改造現有異步函數API,讓其返回promise方法,從而支持異步函數語法
const promisify = require('util').promisify;
// 調用promisify方法改造現有異步API 讓其返回promise對象
const readFile = promisify(fs.readFile);

async function run() {
   let r1 = await readFile('./01.js', 'utf8');
   let r2 = await readFile('./02.js', 'utf8');
   let r3 = await readFile('./03.js', 'utf8');
   console.log(r1);
   console.log(r2);
   console.log(r3);
}
run();
相關文章
相關標籤/搜索