回调函数 promise async/await全分析

回调函数

获取异步操作的结果

在这里插入图片描述

不成立情况

	function add(x,y) {
		console.log(1)
		setTimeout(() => {
			console.log(2)
			var ret = x + y
			return ret
		}, 1000);
		console.log(3)
		//到这里执行结束 不会等待定时器 
	}

	console.log(add(10,20))

结果

1
3
undfine
2

回调函数

	function add(x,y,callback) {
		//callback就是回调函数
        //var callback = function(ret){console.log(ret)}
		console.log(1)
		setTimeout(() => {
			console.log(2)
			var ret = x + y
			callback(ret)
		}, 1000);
	}

	add(10,20,function (ret) {
		console.log(ret)
	})

Promise

无法决定输出顺序 (异步)

回调地狱:

在这里插入图片描述

异步代码:无法决定输出顺序

eg:

在这里插入图片描述

输出结果:

在这里插入图片描述

决定输出顺序

回调地狱

套娃

const fs = require('fs')

fs.readFile('./data/a.txt','utf8',function (err,data) {
    if(err){
        // return console.log('err')
        // 抛出异常
        //  1.阻止程序执行
        //  2.把错误消息打印打控制台
        throw err
    }
    console.log(data)
    fs.readFile('./data/b.txt','utf8',function (err,data) {
        if(err){
            // return console.log('err')
            // 抛出异常
            //  1.阻止程序执行
            //  2.把错误消息打印打控制台
            throw err
        }
        console.log(data)
        
        fs.readFile('./data/c.txt','utf8',function (err,data) {
            if(err){
                // return console.log('err')
                // 抛出异常
                //  1.阻止程序执行
                //  2.把错误消息打印打控制台
                throw err
            }
            console.log(data)
        })
    })
})

结果 顺序正确

在这里插入图片描述

Promise解决回调地狱

理解

在这里插入图片描述

小例子
var fs = require('fs')

//ES6 promise

//1 创建一个Promise 容器
console.log(1)
new Promise(function () {
    console.log(2)
    fs.readFile('./data/a.txt','utf8',function (err,data) {
        if(err){
            //失败了

        }else{
            //成功了
            console.log(3)
        }
    })
})
console.log(4)
//输出结果
1 2 4 31 到promise 24 最后promise结束 3
正式使用

基本语法

var p1 = new Promise(function (resolve,reject) {
    fs.readFile('./data/a.txt','utf8',function (err,data) {
        if(err){
            //失败了
            reject(err)
        }else{
            //成功了
            resolve(data)
        }
    })
})

//then 中的data 就是 resolve(data)的data 
//catch 中的err 就是 reject(err)err 
p1.then((data)=>{
    console.log(data)
}).catch((err)=>{
    console.log('失败',err)
})
实现效果
var fs = require('fs')

//ES6 promise

//1 创建一个Promise 容器
var p1 = new Promise(function (resolve,reject) {

    fs.readFile('./data/a.txt','utf8',function (err,data) {
        if(err){
            //失败了
            reject(err)
        }else{
            //成功了
            resolve(data)
        }
    })
})

var p2 = new Promise(function (resolve,reject) {

    fs.readFile('./data/b.txt','utf8',function (err,data) {
        if(err){
            //失败了
            reject(err)
        }else{
            //成功了
            resolve(data)
        }
    })
})

var p3 = new Promise(function (resolve,reject) {

    fs.readFile('./data/c.txt','utf8',function (err,data) {
        if(err){
            //失败了
            reject(err)
        }else{
            //成功了
            resolve(data)
        }
    })
})

//then 中的data 就是 resolve(data)的data 
//catch 中的err 就是 reject(err)err 
p1.then((data)=>{
    console.log(data,'p1')
    //当 p1 读取成功的时候
    //当前函数中return 的结果就可以在后面的then 中 function 接收到
    //当你 return 123 后面就能接收到 123
    //  return 'hello' 后面就接收到 'hello'
    //  没有 return 后面收到的就是 undefined
    //上面那些return的数据没什么用
    //真正有用的是:我们可以 return 一个 Promise
    //当return 一个 Promise 对象的时候,后续的then中的方法 的第一个参赛会作为 p2的 resolve
    return p2
}).catch((err)=>{
    console.log('失败',err)
})
.then((data)=>{
    console.log(data,'p2')
    return p3
})
.then((data)=>{
    console.log(data,'p3')
})

在这里插入图片描述

在这里插入图片描述

封装promise API

封装

function pReadFile(filrPath) {
    return new Promise(function (resolve,reject) {

        fs.readFile(filrPath,'utf8',function (err,data) {
            if(err){
                //失败了
                reject(err)
            }else{
                //成功了
                resolve(data)
            }
        })
    })
}

使用

pReadFile('./data/a.txt')
    .then((data)=>{
        console.log(data,'p1')
        return pReadFile('./data/b.txt')
    })
    .then((data)=>{
        console.log(data,'p2')
        return pReadFile('./data/c.txt')
    })
    .then((data)=>{
        console.log(data,'p3')
    })

结果

在这里插入图片描述

Promise使用场景

应用场景

get('data.json',function (data1) {
    console.log(data)
    get('data22.json',function (data2) {
        console.log(data2)
    })
})

Promise

var data = {}

return new Promise(()=>{
    get('data.json')
})
    .then((data1)=>{
    data.user = data1
    return new Promise(()=>{
        get('data22.json')
    })
})
    .then((data2)=>{
    data.jobs = data2
})

axios 使用Promise场景

先封装

export default {
    
    fetchData (url, methods, datas) {
        return new Promise((resolve, reject) => {
          axios({
              url: url,
              method: methods,
              data: datas
            }).then((res) => {
              resolve(res)
            }).catch(function (error) {
              reject(error)
              // console.log(error);
            })
        })
    }
}

module.exports = api

使用

getData () {
    api.fetchData('https://www.apiopen.top/novelApi','get')
        .then(res=>{
            console.log(res.data,'111');
            return api.fetchData('https://www.apiopen.top/novelApi','get')
        },error => {
            console.log(error)
        })
        .then(res=>{
            console.log(res.data,'222');
            return api.fetchData('https://www.apiopen.top/novelApi','get')
        },error => {
            console.log(error)
        })
    	
}

async和await

async

async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行。

使用:

async function timeout() {
  return 'hello world';
}

console.log(timeout());

输出结果:调用会返回一个promise 对象。

在这里插入图片描述

通过.then输出结果

在这里插入图片描述

异步函数

async function timeout() {
    return 'hello world'
}
timeout().then(result => {
    console.log(result);
})
console.log('虽然在后面,但是我先执行');

结果

在这里插入图片描述

await (等待)

await 关键字只能放到async 函数里面

现在写一个函数,让它返回promise 对象,该函数的作用是2s 之后让数值乘以2

// 2s 之后返回双倍的值
function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
}

async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result);
}

testResult();

2秒后输出:

在这里插入图片描述

等待promise执行后输出

示例二

function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
}

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log(first + second + third);
}

testResult();

6秒后输出:

在这里插入图片描述

async和await的应用场景

假设我们有如下两个方法

  function convertToBase64Data(url) { // 转成base64格式
    return new Promise( resolve => {
      setTimeout( () => {
        resolve('img');
      }, 1000);
    });
  }
  function saveToLocal(img) { // 保存到本地
    return new Promise( resolve=> {
      setTimeout( () => {
        resolve('success');
      }, 200);
    });
  }

场景1:

多个异步需要按顺序:图片处理完成然后保存在本地

promise版

    function fn1() {
        return convertToBase64Data('http://1.jpg').then( base64Data => {
            return saveToLocal(base64Data);
        })
    }

async await版:

  async function fn1() {
    const base64Data = await download('http://1.jpg');
    const result = await saveToLocal(base64Data); 
    return result;
  }

场景2:

图片需要同时处理,但是要按顺序一张一张保存在本地

async function fn2() {
        // 同时处理两张
        const promise1 = convertToBase64Data('http://1.jpg');
        const promise2 = convertToBase64Data('http://2.jpg');
        const [data1, data2] = await Promise.all([promise1, promise2]);
        // 先保存第一张
        const result = await saveToLocal(data1);
        // 再保存第二张
        const result2 = await saveToLocal(data2);
    }

场景3:

多张图片,处理一张保存一张,然后才能处理下一张

async function fn3() {
        const imgUrls = ['http://1.jpg', 'http://2.jpg', 'http://3.jpg', 'http://4.jpg', 'http://5.jpg'];
        for (let i = 0; i < imgUrls.length; i++) {
          const base64Data = await convertToBase64Data(imgUrls[i]);
          const result = await saveToLocal(base64Data);
          console.log(result);
        }
    }

场景4:

条件语句

async function fn4(needConvertToBase64) {
    const img = await download('http://1.jpg');
    if (needConvertToBase64) {
      const base64Data = await convertToBase64(img);
      return base64Data;
    }
    return img;
  }

场景5:

你可能会这样:调用方法1,使用方法1返回的结果去调用方法2,然后使用两者的结果去调用方法3。

假设有如下业务: 获取用户ID,然后根据ID获取用户信息,然后将两者保存在服务器。

function getUserId() {
    return Promise.resolve('123123');
  }
  function getUserInfo(id) {
    return Promise.resolve({name: 'aaron'});
  }
  function saveToServer(id, userInfo) {
    return Promise.resolve('success');
  }

你的代码很可能是这样的:

 function fn5() {
    return getUserId().then( id => { // 拿到id
      return getUserInfo(id).then( userInfo => {
        return saveToServer(id, userInfo);
      });
    });
  }

使用await:

 async function fn5() {// 使用await
    const id = await getUserId();
    const userInfo = await getUserInfo(id);
    return saveToServer(id, userInfo);
  }

场景6:

错误处理

使用await,try/catch捕获错误

async function fn6() {
    try {
      const data = await convertToBase64('http://1.jpg');
      const result = await saveToLocal(data);
      console.log(result);
    } catch (err) {
      console.log(err);
    }
  }

=> { // 拿到id
return getUserInfo(id).then( userInfo => {
return saveToServer(id, userInfo);
});
});
}


使用await:

```js
 async function fn5() {// 使用await
    const id = await getUserId();
    const userInfo = await getUserInfo(id);
    return saveToServer(id, userInfo);
  }

场景6:

错误处理

使用await,try/catch捕获错误

async function fn6() {
    try {
      const data = await convertToBase64('http://1.jpg');
      const result = await saveToLocal(data);
      console.log(result);
    } catch (err) {
      console.log(err);
    }
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值