Node.js异步编程~超级详细哦

下面是对Node.js异步编程的整理,希望可以帮助到有需要的小伙伴~

文章目录

      • 同步API,异步API
      • 同步API,异步API的区别
        • 获取返回值的方式不同
        • 代码执行顺序不同
      • Node.js中的异步API
      • Promise
      • 通过Promise解决回调地狱
      • 异步函数

同步API,异步API

同步API:只有当API执行完成后,才能继续执行下一个API

异步API:当前API的执行不会阻塞后续代码的执行

// 同步编程
/* 
console.log("before");
console.log("after"); 
// before
// after
*/

// 异步编程
console.log('before');
setTimeout(
    () => {
     
        console.log('last')
    },2000);

console.log('after');
/* 
before
after
last
// before执行后,2秒钟后再执行last,在这2秒钟的时间里after执行了
*/

同步API,异步API的区别

获取返回值的方式不同

同步API可以从返回值中拿到API执行的结果

异步API必须通过回调函数拿到异步操作的执行结果

通过回调函数获取异步函数的返回值

回调函数:

别人调用自己定义的函数

// 回调函数的定义
function getData (callback) {
     }
// 回调函数的调用
getData ( ()=>{
     } );// getData()里面的实参()=>{} 对应的是 callback形参;即在getData()函数内部调用了()=>{}函数

通过回调函数获取异步函数的返回值示例:

/* function getMsg () {
    setTimeout(function () {
        return {
            msg:'hello node.js'
        }
    },2000)
}

const msg = getMsg();
console.log(msg); // undefined

// 2秒后才可以执行定时器里面的内容 
// 所以返回值是函数的默认返回值undefined */


// 可以通过回调函数获取到异步操作的执行结果
function getMsg (callback) {
     
    setTimeout(function () {
     
        callback({
     
            msg:'hello node.js'
        })
    },2000)
}

getMsg(function (data){
     
    console.log(data); // { msg: 'hello node.js' }
})

代码执行顺序不同

Node.js从上而下依次执行代码

遇到同步API就拿到同步代码执行区去执行

遇到异步API就拿到异步代码执行区,但是不会执行异步代码,

当所有的同步代码执行完毕后,再到异步代码执行区依次执行代码

当异步代码执行完毕后,系统会去回调函数队列中找异步API对应的回调函数,把回调函数放到同步代码执行去区执行

同步API从上到下依次执行,前面代码会阻塞后面代码的执行

for (var i=0;i<10;i++) {
     
    console.log(i)
}
console.log("循环外")
// 0 1 2 3 4 5 6 7 8 9 循环外

异步API不会等待API执行完成后再向下执行代码

console.log('代码开始执行')
setTimeout(function(){
     
    console.log('2s后执行')
},2000)

setTimeout(function(){
     
    console.log('0s后执行')
})

console.log('代码结束执行')

/* 代码开始执行
代码结束执行
0s后执行
2s后执行 */

Node.js异步编程~超级详细哦_第1张图片

Node.js中的异步API

异步编程的返回结果是通过回调函数获取的

在异步编程中,前面代码的执行不会阻碍后面代码的执行,但是有时候后面代码的执行会依赖前面代码的执行结果,这时可以通过多个回调函数来完成。

读取文件就是通过回调函数返回结果的,如果依次读取多个文件,就需要多次调用回调函数

示例如下:

// 依次读取1.txt、 2.txt 、 3.txt文件

// 导入文件模块
const fs = require('fs');
// 读取文件
fs.readFile('./1.txt','utf8',(err,result1) => {
     
    console.log(result1)
    fs.readFile('./2.txt','utf8',(err,result2) => {
     
        console.log(result2)
        fs.readFile('./3.txt','utf8',(err,result3) => {
     
            console.log(result3)
        })
    })
})
/* 
// 结果:
1
2
3 
*/

如果需要写很多个回调函数的话,就会造成回调地狱,promise可以解决回调地狱问题。

Promise

Promise出现的目的是解决Node.js异步编程中回调地狱的问题。

Promise是一个构造函数

Promise语法

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)); // 失败了
  • resolve:将异步API的执行结果传递到整个Promise的外面(resolve是一个方法)
  • reject:如果异步API执行失败,就把失败的结果传递到整个Promise的外面 (reject是一个方法)

通过Promise对象的then方法获取到异步的执行结果。

通过Promise解决回调地狱

// 依次读取1.txt、 2.txt 、 3.txt文件

// 导入文件模块
const fs = require('fs');
const {
      resolve } = require('path');
// 读取文件
/* fs.readFile('./1.txt','utf8',(err,result1) => {
    console.log(result1)
    fs.readFile('./2.txt','utf8',(err,result2) => {
        console.log(result2)
        fs.readFile('./3.txt','utf8',(err,result3) => {
            console.log(result3)
        })
    })
}) */

function p1() {
     
    return new Promise((resolve,reject) => {
     
        fs.readFile('./1.txt','utf8',(err,result) => {
     
            resolve(result)
        })
    })
}

function p2(){
     
    return new Promise((resolve,reject) => {
     
        fs.readFile('./2.txt','utf8',(err,result) => {
     
            resolve(result);
        })
    })
}

function p3(){
     
    return new Promise((resolve,reject) => {
     
        fs.readFile('./3.txt','utf8',(err,result) => {
     
            resolve(result);
        })
    })
}

p1().then((r1) => {
     
    console.log(r1);
    return p2();
})
.then((r2) => {
     
    console.log(r2);
    return p3();
}) 
.then((r3) => {
     
    console.log(r3);
})

// 相当于

/* p1().then((r1) => {
    console.log(r1);
});

p2().then((r2) => {
    console.log(r2);
});

p3().then((r3) => {
    console.log(r3);
}); */

/* 
// 结果:
1
2
3
*/

异步函数

使用Promise可以解决回调地狱的问题,但是会产生代码冗余,可以使用ES 7提供的回调函数解决回调地狱的问题并且代码更加简单明了。

异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。

const fn = async () => {
     };

async关键字:

  1. 普通函数定义前加async关键字普通函数变成异步函数
  2. 异步函数默认返回promise对象
  3. 在异步函数内部使用return关键字进行结果返回,结果会被包裹在promise对象中
  4. return关键字代替了resolve方法
  5. 在异步函数内部使用throw关键字抛出程序异常
  6. 调用异步函数再链式调用then方法获取异步函数执行结果
  7. 调用异步函数再链式调用catch方法获取异步函数执行的错误信息

await关键字:

  1. await关键字只能出现在异步函数中
  2. await promise ;await后面只能写promise对象写其他类型的API是不可以的
  3. await关键字可是暂停异步函数向下执行直到promise返回结果

示例:

const fs = require('fs');
// fs中readFile()方法的返回结果不是Promise类型的,不能使用异步函数中的await关键字
// uitl模块的promisify()方法可以将返回的结果改为Primise类型
// 没有调用promisify方法,没有写promisify()
// 改在现有异步函数的API,让其返回promise对象,从而支持异步函数语法
const promisify = require('util').promisify;
// 调用了promisify()方法,但没有调用readFile()方法
// 调用promisify方法改造现有异步API,让其返回promise对象
const readFile = promisify(fs.readFile);

async function run() {
     
    // 调用readFile()方法,该方法的返回结果回改成promise类型
    let r1 = await readFile('./1.txt','utf8')
    let r2 = await readFile('./2.txt','utf8')
    let r3 = await readFile('./3.txt','utf8')
    console.log(r1)
    console.log(r2)
    console.log(r3)
}

run();

// 返回结果:
// 1
// 2
// 3

end~
对Node.js异步编程的介绍到这里就结束啦~
希望可以对你有所帮助~
如果有错误,请大佬指正,万分感谢!

你可能感兴趣的:(Node)