回调地域解决 和 axios

1,478 阅读5分钟

promise

  • Promise 是一个构造函数
  • Promise.prototype 上有 .then 和 .catch 方法
  • Promise 表示异步操作

const p = new Promise() 表示创建了一个形式上的 异步操作 因为不知道是什么具体的异步操作。

具体的异步操作 写在 Promise(function(){})中。比如 读文件 就是一个异步操作

 	const p = new Promise(function(){
        fs.readFile('文件1路径', ' utf-8 ', function(err , data){
            if(err){
                console.log(err.message)
            }
            else{
                console.log(data)
            }
        })
    })

众所周知,异步操作返回的最终结果是没有固定顺序的,是按照哪个执行快哪个先返回结果

	const p = new Promise(function(){ fs.readFile('文件1路径'), 'utf-8', function(){...} }) //文件1 内容是 111
	
	const p2 = new Promise(function(){ fs.readFile('文件2路径'), 'utf-8', function(){...} }) //文件2 内容是 222

	const p3 = new Promise(function(){ fs.readFile('文件3路径'), 'utf-8', function(){...} }) //文件3 内容是 333

就像上面的代码一样,最终输出的结果 不一定是 111-222-333,也有可能是 111-333-222 等等 三种内容打乱顺序输出。因为读文件 是异步操作

那么我要一些异步操作返回的结果按照一定的顺序执行怎么办呢?比如让文件内容按照 111-222-333 顺序返回

const p = new Promise(function(){
	fs.readFile('文件1路径'', ,function(err, data){
		if (err) {}
    	else{
           console.log(data);
		   fs.readFile('文件2路径'',,function(err,data){
			if (err) {}
        	else{
            	console.log(data);
				fs.readFile('文件3路径'',,function(err,data){...}
				}
			})

		}
	}) 
})

可以在第一个文件成功读取后的回调函数中 读取第二个文件 在第二个文件成功读取后的回调函数中 读取第三个文件。这样就可以按照顺序读出 111-222-333 了

但是这样那么多 函数嵌套 在这么大一段代码中 极其难看 且 不易维护 ,我突然想调换一下文件内容顺序 还要重新 调整 大段代码 。

那么怎么办呢?

.then 和 .catch


其实在Promise 中的 function 函数中两个有两个参数 ,这两个参数分别是 读取文件成功后的回调函数 successCallback 还有 读取文件失败后的回调函数 errorCallback

 	const p = new Promise(function (successCallback, errorCallback){
 		fs.readFile('文件路径','utf-8',function(err,data){
            if(err){
                errorCallback(err.message)
            }
            else{
				successCallback(data)
            }
        })
 	})

这两个 回调函数 暂时 是没有内容的,Promise 对象 拥有 .then.catch 方法, 可以用来定义 successCallback 和 errorCallback 回调函数内容

  • then(function( ){ } , function ( ) { }) 对应 successCallback , errorCallback
  • catch( function( ){ } ) 对应 errorCallback

我们先把这个 读文件的 异步操作 封装 成一个函数 以备调用 方便

function getContentFile( fpath ){
	const p = new Promise(function(successCallback, errorCallback){
     	fs.readFile(fpath,'utf-8', function(err,data){
            if(err){
                successCallback(err.message)
            }
            else{
                errorCallback(data)
            }
    	})   
    })

}

我们需要 这个 getContentFile( ) 函数 返回一个 Promise 对象 我们才能使用 .then 和 . catch 方法。 所以我们 return new Promise()

	function getContentFlie( fpath ){
		return new Promise(function(successCallback, errorCallback){...})
                                                             	}

在来调用这个 getContentFile 函数

var p = getContentFile('文件1路径') //返回的是一个 promise 对象
p.then(function(data){
	console.log(data)
	return getContentFile('文件2路径') //返回的是一个 promise对象这样就可以继续调用 then 方法
}).then(function (data){
    console.log(data)
    return getContentFile('文件3 路径') 
}).then(function (data){
    console.log(data)
}).catch(function (err) {
    console.log(err.message)
})//最后在末尾添加 catch 方法 来统一 定义失败回调函数 内容

这样相对于 前面的回调函数 代码简洁多了 但是只是相对于前面的代码来说.

可我还是觉得很丑难维护怎么说?

await 和 async


这时候就轮到 awaitasync 出场了 , 这两个是修饰符. 使用他俩 直接简化 .then 操作. 可以直接拿来用 不用在 .then

await 只能用在被 async 修饰的方法中

如果 某个方法的返回值是 Promise 实例对象,那么 就可以用 await 关键字 ,来修饰 promise 实例

先把上面封装好的读文件 异步操作 拿下来

//返回 promise 对象
function getContextFile (fpath){
	return new Promise(function (successCallback, errorCallback){
	 	fs.readFile(fpath,'utf-8',function (err, data){
	 		if (err) {  return errorCallback(err.message); }
	 		else{ return successCallback(data);	}
	 	})
	 })
}

//await 修饰异步操作 , async 修饰 包含 await修饰异步操作 的方法
async function test(){
        const data1 = await getContextFile('文件1 路径')
        //修饰完后的getContextFile  使 data1 拿到 成功读取 文件1 的内容, 不用在 data1.then 来设置回调函数
        console.log(data1) 
}

test()

调用一下 test 函数, 这样是可以输出文件1 的内容的 牛不牛

当然要是遇到读取失败怎么办.直接在后面加上 catch 方法

async function test(){
        const data1 = await getContextFile('文件1 路径').catch(function (err){return err})
        if(data1 instanceof Error){
        	console.log('读取文件失败')
        }else{        
        	console.log(data) 
        }
}

按照顺序来的话 直接在 test 函数 中 按照顺序 多来调用 几次 getContextFile 就行

async function test(){
        const data1 = await getContextFile('文件1 路径') ....
        console.log(data1)
        
        const data2 = await getContextFile('文件2 路径') ....
        console.log(data2)
    
        const data2 = await getContextFile('文件3 路径') ....
		console.log(data3)
}

test() //输出结果 111 222 333

异步操作不能按顺序 输出. 这样使得 异步操作 像 非异步操作一样 按照顺序输出.

axios

axios 是用来发起 AJAX 请求的 发起AJAX请求也是异步的, axios.get 和 axios.post 返回的 是 promise 对象

Getinfo(){
	const result = axios.get('http://www.liulongbin.top:3005/api/get')
    
    
	result.then(function(res){
        console.log(res)
    })
}

		// 上面这么写太麻烦了 简化一下。 axios.get 返回的是一个promise 对象 就可以用 await 来修饰,用了 await 来修饰异步操作, 那么就得用 async 来修饰函数。
		// 我们要的只是请求回来对象中 的一个 data 属性。利用 axios 请求回来的 promise 对象自带 6个属性。
		// 其实我们最终要拿到的是其中 data 属性(解放 data 属性)中的data。可以利用 解构赋值
		// 例如
		// car{
		//  	name:'奥迪',
		// 		number:1111
		// }
		// const { name, number } = car
		// console.log(name); //输出了 奥迪
		// 给name起个别名就是
		// const { name: carname ,number}
async	Getinfo(){
	const { data:res }	 = await axios.get('接口')

	console.log(res.data);
}