0
点赞
收藏
分享

微信扫一扫

基于回调函数的异步编程

岁月不饶人老不正经 2022-04-13 阅读 182
javascript

1. 什么是回调函数

回调函数是指通过函数参数的方式将一个函数传递到另一个函数中,参数函数就是回调函数。

function A () {

console . log ( "A is running" )

}

function B ( callback ) {

console . log ( "B Start" )

callback () // A is running

console . log ( "B End" )

}

B ( A )

我们经常将回调函数写成 callback ,实际上它是 call then back 的简写,含义是调用后返回,就是

在主函数中调用参数函数,参数函数调用完成后返回主函数继续执行主函数中的代码。

为什么在 B 函数中不直接调用 A 函数而要通过参数的方式传递进去 ?

通常在编写应用程序时, B 函数都是语言内部或者其他开发者定义好的,我们看不到内部代码或者

说不能直接在他内部代码中插入我们的代码,而我们又想介入程序的执行,此时就可以通过回调函

数的方式将我们的逻辑传递给 B 函数, B 函数在内部再来调用这个回调函数。

2. 回调函数传递参数

在主函数中调用回调函数时,可以为回调函数传递参数。

function A ( arg ) {

console . log ( "A is running" )

console . log ( arg )

}

function B ( callback ) {

console . log ( "B Start" )

callback ( " 我是 B 函数传递给 A 函数的参数 " ) // A is running

console . log ( "B End" )

}

B ( A )

3. 回调函数在异步编程中的应用

在异步编程中,异步 API 执行的结果就是通过回调函数传递参数的方式传递到上层代码中的。

const fs = require ( "fs" )

fs . readFile ( "./index.html" , "utf-8" , function ( error , data ) {

if ( error ) console . log ( " 发生了错误 " )

console . log ( data )

})

4. 回调地狱

回调地狱是回调函数多层嵌套导致代码难以维护的问题。

基于回调函数的异步编程一不小心就会产生回调地狱的问题。

const fs = require ( "fs" )

fs . readFile ( "./x.txt" , "utf-8" , function ( error , x ) {

fs . readFile ( "./y.txt" , "utf-8" , function ( error , y ) {

fs . readFile ( "./z.txt" , "utf-8" , function ( error , z ) {

console . log ( x )

console . log ( y )

console . log ( z )

})

})

})

const x = fs . readFile ( './x.txt' , 'utf-8' )

const y = fs . readFile ( './y.txt' , 'utf-8' )

const z = fs . readFile ( './z.txt' , 'utf-8' )

console . log ( x )

console . log ( y )

console . log ( z )

4.7 基于 Promise 的异步编程

1. Promise 概述

Promise JavaScript 中异步编程解决方案,可以解决回调函数方案中的回调地狱问题。

可以将 Promise 理解为容器,用于包裹异步 API 的容器,当容器中的异步 API 执行完成后,

Promise 允许我们在容器的外面获取异步 API 的执行结果,从而避免回调函数嵌套。

function A ( arg ) {

console . log ( "A is running" )

console . log ( arg )

}

function B ( callback ) {

console . log ( "B Start" )

callback ( " 我是 B 函数传递给 A 函数的参数 " ) // A is running

console . log ( "B End" )

}

B ( A )

const fs = require ( "fs" )

fs . readFile ( "./index.html" , "utf-8" , function ( error , data ) {

if ( error ) console . log ( " 发生了错误 " )

console . log ( data )

})

const fs = require ( "fs" )

fs . readFile ( "./x.txt" , "utf-8" , function ( error , x ) {

fs . readFile ( "./y.txt" , "utf-8" , function ( error , y ) {

fs . readFile ( "./z.txt" , "utf-8" , function ( error , z ) {

console . log ( x )

console . log ( y )

console . log ( z )

})

})

})

const x = fs . readFile ( './x.txt' , 'utf-8' )

const y = fs . readFile ( './y.txt' , 'utf-8' )

const z = fs . readFile ( './z.txt' , 'utf-8' )

console . log ( x )

console . log ( y )

console . log ( z ) Promise 翻译为承若,表示它承若帮我们做一些事情,既然它承若了它就要去做,做就会有一个过

程,就会有一个结果,结果要么是成功要么是失败。

所以在 Promise 中有三种状态 , 分别为等待 (pending) ,成功 (fulfilled) ,失败 (rejected)

默认状态为等待,等待可以变为成功,等待可以变为失败。

状态一旦更改不可改变,成功不能变回等待,失败不能变回等待,成功不能变成失败,失败不能变

成成功。

2. Promise 基础语法

const fs = require ( "fs" )

const promise = new Promise ( function ( resolve , reject ) {

fs . readFile ( "./x.txt" , "utf-8" , function ( error , data ) {

if ( error ) {

// 将状态从等待变为失败

reject ( error )

} else {

// 将状态从等待变为成功

resolve ( data )

}

})

})

promise

. then ( function ( data ) {

console . log ( data )

})

. catch ( function ( error ) {

console . log ( error )

})

3. Promise 链式调用

const fs = require ( "fs" )

function readFile ( path ) {

return new Promise ( function ( resolve , reject ) {

fs . readFile ( path , "utf-8" , function ( error , data ) {

if ( error ) return reject ( error )

resolve ( data )

})

})

}

readFile ( "./x.txt" )

. then ( function ( x ) {

console . log ( x )

return readFile ( "./y.txt" )

})

. then ( function ( y ) {

console . log ( y )

return readFile ( "./z.txt" )

})

. then ( function ( z ) {

console . log ( z )

})

. catch ( function ( error ) {

console . log ( error )

})

. finally ( function () {

console . log ( "finally" )

})

4. Promise.all 并发异步操作

const fs = require ( "fs" )

Promise . all ([

readFile ( "./x.txt" ),

readFile ( "./y.txt" ),

readFile ( "./z.txt" )

]). then ( function ( data ) {

console . log ( data )

})

4.8 基于异步函数的异步编程

Promise 虽然解决了回调地狱的问题,但是代码看起来仍然不简洁。

使用异步函数简化代码提高异步编程体验。

1. 异步函数概述

const fs = require ( "fs" )

function readFile ( path ) {

return new Promise ( function ( resolve , reject ) {

fs . readFile ( path , "utf-8" , function ( error , data ) {

if ( error ) return reject ( error )

resolve ( data )

})

})

}

async function getFileContent () {

let x = await readFile ( "./x.txt" )

let y = await readFile ( "./y.txt" )

let z = await readFile ( "./z.txt" )

return [ x , y , z ]

}

getFileContent (). then ( console . log )

async 声明异步函数的关键字,异步函数的返回值会被自动填充到 Promise 对象中。

await 关键字后面只能放置返回 Promise 对象的 API

await 关键字可以暂停函数执行,等待 Promise 执行完后返回执行结果。

await 关键字只能出现在异步函数中。

2. util.promisify

Node.js 平台下,所有异步方法使用的都是基于回调函数的异步编程。为了使用异步函数提高异

步编程体验,可以使用 util 模块下面的 promisify 方法将基于回调函数的异步 API 转换成返回

Promise API

const fs = require ( "fs" )

const util = require ( "util" )

const readFile = util . promisify ( fs . readFile )

async function getFileContent () {

let x = await readFile ( "./x.txt" , "utf-8" )

let y = await readFile ( "./y.txt" , "utf-8" )

let z = await readFile ( "./z.txt" , "utf-8" )

return [ x , y , z ]

}

getFileContent (). then ( console . log )

举报

相关推荐

0 条评论