pormise
假设现在我刚认识你,需要和你说话,但是我普通话不够标准,需要间隔一秒钟才能说一句话,以此让你可以慢慢思考。这样的话我们就需要用到定时器。
最沙雕的代码如下:
setTimeout( function(){ console.log('你好,我是saoge'); setTimeout( function(){ console.log('很高兴认识你'); setTimeout( function(){ console.log('交个朋友吧'); },1000) },1000) },1000)
但是这种代码,是根本没有可读性的。因此我们还有另一种写法。
function helloOne(next){ setTimeout(function(){ console.log('你好,我是saoge'); next(); },1000) } function helloTow(next){ setTimeout(function(){ console.log('你好,很高兴认识你'); next(); },1000) } function helloThree(){ setTimeout(function(){ console.log('交个朋友吧'); },1000) } helloOne(function(){ helloTow(function(){ helloThree() }) })
用回调函数来实现代码看上去会有逻辑性的多,但是在调用的时候也会存在层层嵌套的问题,如果这个时候我是个话痨,要和你说很多据话,那么用回调函数写出来的代码也是相当恐怖的,而且采用这种方式并不能很方便的改变执行的顺序等。总而言之就是因为总总不好,所以出现了更好的方式promise。
使用Promise
使用new来创建一个Promise的实例。
var promise = new Promise(function(resolve,reject){ setTimeout(function(){ resolve('你好,我是saoge'); reject(new Error('发生错误')); // if(false){ // resolve('你好,我是saoge'); // }else{ // reject(new Error('发生错误')) // } },1000) }) promise.then(function(data){ console.log(data); },function(err){ console.log(err) }) //使用catch promise.then(function(data){ console.log(data); }).catch(function(err){ console.log(err); })
我们来一步一步的分析上述案例。
在上述实例中,Promise传入了两个形参 resolve 和 reject 这两个参数的回调,代表成功和失败,如果执行正常,就调用resolve,否则就调用reject。上代码:
var promise = new Promise(function(resolve,reject){ //成功时调用resolve //失败时调用reject })
同时,promise实例具有then方法,then方法接受两个参数,第一个参数时resolve执行成功的回调,第二个参数reject 是执行失败的回调。
因此,在上述案例中,最终会输出 "你好我是骚哥"
我们可以用if语句来模拟一下执行失败的情况,这个时候输出的就是 Error:发生错误
同时,Promise实例还提供了一个catch()方法,该方法和then()方法接收的第二个参数一样,用来执行reject的回调。
var promise = new Promise(function(resolve,reject){ //成功时调用resolve //失败时调用reject }) promise.then( resolve的回调 , reject 的回调(可选) ); promise.catch(reject的回调);
我们用Promise来实现一下最初对话的案例。
function helloOne() { return new Promise( function(next) { setTimeout(function() { console.log('你好,我是saoge'); next(); }, 1000) }) } function helloTwo() { return new Promise( function(next) { setTimeout(function() { console.log('你好,很高兴认识你'); next(); }, 1000) }) } function helloThree() { return new Promise( function(next) { setTimeout(function() { console.log('交个朋友吧'); next(); }, 1000) }) } helloOne().then(helloTwo).then(helloThree);
和使用回调的区别在于,我们将要执行的代码放在了Promise实例中,这样,在我们最后需要执行的时候,只需要用then()方法去调用即可,语法结构简单,即使我想说再多的话也不会造成代码结构混乱。且在这里使用了Promise方法之后,如果是我想要改变代码执行顺序的话只需要改变then()方法传入的值即可。
异步之间传参
function hello(){ var text='你好,我是saoge'; setTimeout(function(){ console.log(text); say(text); },1000) } function say(text){ setTimeout(function(){ console.log(text) },1000) } hello();
Promise在执行成功的时候,会调用resolve,因此,我们就可以用resolve来传值。
var pro = new Promise((resolve, reject) => { setTimeout(function() { var text = '你好,我是saoge'; console.log(text); resolve(text); }, 1000) }) pro.then(function(data) { setTimeout(function() { console.log(data); }, 1000) })
需要等待多个函数执行完毕再执行时:Promise.all()
function helloOne() { return new Promise( function(next) { setTimeout(function() { console.log('你好,我是saoge'); next(); }, 1000) }) } function helloTwo() { return new Promise( function(next) { setTimeout(function() { console.log('你好,很高兴认识你'); next(); }, 2000) }) } function helloThree() { return new Promise( function(next) { setTimeout(function() { console.log('交个朋友吧'); next(); }, 3000) }) } Promise.all([helloOne(),helloTwo(),helloThree()]).then(function(){ setTimeout(function(){ console.log('可以吗?') },1000) });
上面这段代码就会先在一秒钟我说出你好,我是骚哥。然后再过一秒钟我说你好,很高兴认识你。再过一秒钟说出交个朋友吧,我们可以看到在then()方法里面有一个函数,是一秒钟之后询问你可以吗?而这句话执行的时间是第四秒。也就是Promise.all中的函数执行完成之后再去执行hten()方法中的语句。
Promise.race()
function helloOne() { return new Promise( function(next) { setTimeout(function() { console.log('你好,我是saoge'); next(); }, 1000) }) } function helloTwo() { return new Promise( function(next) { setTimeout(function() { console.log('你好,很高兴认识你'); next(); }, 2000) }) } function helloThree() { return new Promise( function(next) { setTimeout(function() { console.log('交个朋友吧'); next(); }, 3000) }) } Promise.race([helloOne(),helloTwo(),helloThree()]).then(function(){ setTimeout(function(){ console.log('可以吗?') },1000) });
看上面这个例子,执行一秒之后输出“你好,我是骚哥”,然后再过一秒钟会输出两句话,“你好,很高兴认识你”,“可以吗?”,最后再输出“交个朋友吧” 可以看出,在helloOne执行完毕之后,then()中的代码就开始执行了,和Promise.all()的不同就在于,只要有一个执行成功就去执行hten()中的代码。
async
1.async干了什么
async function helloOne(){ setTimeout(function(){ return("你好,我是骚哥"); },1000) } console.log(helloOne()) //Promise {<fulfilled>: undefined}
async 返回的是一个Promise对象。
async function helloOne(){ setTimeout(function(){ return("你好,我是骚哥"); },1000) } console.log(helloOne()); //Promise {<fulfilled>: undefined} helloOne().then(function(data){ console.log(data) //undefined })
我们尝试用then()去获取async函数中的值,但是返回的是undefined,且两个输出语句是同时执行的,所以说then()中的函数还没有等到异步函数执行完便执行了,因此这里和Promise不太一样。
function helloOne() { return new Promise((resolve,reject)=>{ setTimeout( function(){ resolve( '你好,我是saoge'); }, 1000) }); } function helloTwo(){ setTimeout( function(){ return '拜拜'; }, 1000) } async function say(){ var one = await helloOne() console.log(one) //你好,我是saoge var two = await helloTwo() console.log(two) //undefined } say()
直接看代码,可以发现,如果await 后面跟的是一个Promise对象,那么将会等到Promise对象resolve,然后将resolve的值作为表达式的结果。如果不是以恶搞promise对象,那么await的运算结果就是此时传入的东西,兵不会有其他作用。