异步处理方法回调函数、Promise、async

在开发过程中经常会遇到一些异步操作,比如ajax请求,node读取写入文件,定时任务等等。通常情况下需要捕获异步返回的数据,从而进行下一步操作,下面介绍一下几种处理异步执行的方法

CallBack回调事件

callback,事件回调,异步处理完成,通过事件的调用,从而达到异步处理要求。经典的有ajax请求,node文件操作等,下面看一下node非阻塞代码实例:

var fs = require("fs");
var path = require("path");
fs.readFile(path.join(__dirname, '../public/user.json'), (err, data) => {
    if(err) throw err;
    let list = JSON.parse(data);
	console.log(list);
})

这里readFile函数的第二个参数便是异步处理完成的回调函数

Promise

Promise是开发中经常用到的异步处理方法,下面介绍下promise的常用方法:

  • 基本使用,已setTimeout为例,定义一个promise的对象,一分钟后生成一个10以内的随机数,并判断随机数的大小模拟异步操作成功失败,大于5则成功,在then获取random的值,失败同理
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        let random = Math.random() * 10;
        if(random > 5)
            resolve(random);
        else 
            reject(random);
    }, 1000)
})
promise
	.then(res => {
	    console.log(res, 'res')
	})
	.catch(err => {
	    console.log(err, 'rej')
	})
  • Promise.all:开发过程中有时会遇到,需要同时处理几个接口返回数据的情况,这种就需要捕获几个接口都结束的状态,promise.all就解决了这个问题。该方法接收一个数组作为参数,数组里面的每一项都为一个promise对象,具体如下,新建两个promise对象,一个1s返回 ‘promise1’,一个2s返回 ‘promise2’,使用all之后便在2s后返回一个数组:['promise1', 'promise2']
let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1')
    }, 1000);
});
let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise2');
    }, 2000);
})
Promise.all([promise1, promise2])
    .then(res => {
        console.log(res, 'res'); // 2s 后打印 ['promise1', 'promise2']
    })
    .catch(err => {
        console.log(err, 'rej');
    })

如果有一个promise失败了,则在catch中捕获的便是该promise对象的错误信息,如下:

let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1')
    }, 1000);
});
let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('promise2');
    }, 2000);
})
Promise.all([promise1, promise2])
    .then(res => {
        console.log(res, 'res'); 
    })
    .catch(err => {
        console.log(err, 'rej'); // 2s 后打印出 'promise2'
    })
  • promise.race,竞速,不管成功或者失败,都返回最先完成的promise对象,下列代码便返回最快的1s执行完成的对象
let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1')
    }, 1000)
})
let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise2')
    }, 2000)
})
Promise.race([promise1, promise2])
    .then(res => {
        console.log(res, 'res') // 打印出最快1s完成的'promise1'
    })
    .catch(err => {
        console.log(err, 'rej') //错误也是同理
    })

async awite

promsie解决了异步的困扰,但是存在一个问题:链式回调。这使得代码不容易阅读,async写法则解决了这个问题。

  • async函数返回的是一个promise的对象
getResult: async function (vm) {
  return 'hello word'
}
getResult.then(res => {
	console.log(res); // hello word
})
  • awite必须在有标记async的函数中使用,当执行到awite标记时,并且awite后是一个promise,便会等待promise对象执行完成,才会继续往下执行成功则返回r1的数据,被回调函数then捕获。 当promise失败时便会跳出,并被函数catch捕获
function getResult() {
  return new Promise((resolve, reject) => {
        setTimeout(() => {
            let r1 = Math.ceil(Math.random() * 10);
            console.log(r1);
            resolve(r1);
        }, 1000)
    })
}
(async function(){
    let r1 = await getResult();
    console.log('等待r1完成后执行'); //这里会在1s后执行,getResult失败则不会执行这里
    return r1;
})()
 .then(res => {
     console.log(res); // getResult成功执行后会返回随机生成的 r1
 })
 .catch(err => {
     console.log(err); // getResult执行失败后,会被catch捕获,包括错误信息
 })
  • 解决promise链式回调问题:在开发过程中会存在一个接口调用需要另一个接口返回的数据时,需要在promsie.then中继续调用接口,当这种关系存在很多个的时候就会出现下面这种情况。随机生成三个数,求三个数相加的和,最后的链式回调就看起来特别乱,也不好管理。(当然这里可以用promise.all来实现,但是一旦接口中请求参数需要依赖上一个接口返回的结果则还是需要链式回调)
function getR1() {
   return new Promise((resolve, reject) => {
       setTimeout(() => {
           let r1 = Math.ceil(Math.random() * 10);
           resolve(r1);
       }, 1000);
   });
}
function getR2(r1) {
   return new Promise((resolve, reject) => {
       setTimeout(() => {
           let r2 = Math.ceil(Math.random() * 10);
           resolve(r2);
       }, 1000);
   });
}
function getR3(r1, r2) {
   return new Promise((resolve, reject) => {
       setTimeout(() => {
           let r3 = Math.ceil(Math.random() * 10);
           resolve(r1 + r2 + r3);
       }, 1000);
   });
}
getR1()
   .then(r1 => {
   	   console.log(r1); // 1s 后打印一个随机数的值
       getR2(r1)
           .then(r2 => {
           	   console.log(r1 + r2); // 2s 后打印二个随机数的和
               getR3(r1, r2)
                   .then(r3 => {
                       console.log(r1 + r2 + r3); // 3s 后打印三个随机数的和
                   })
           })
   })

async完美解决,下面代码看起来是不是清晰多了

(async function(){
    let r1 = await getR1();
    let r2 = await getR2();
    let r3 = await getR3();
    console.log('等待3s后执行:', r1 + r2 + r3);
})()

promise对象执行失败捕获

(async function(){
	 let r1 = await getR1().catch(err => {
	     console.log(err);
	 });
})()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值