实现sleep
1 2 3 4 5 6 7 8 9
| async function sleep(delay){ return new Promise((resolve)=>setTimeout(resolve,delay)); } async function foo(){ const t0=Date.now(); await sleep(1500); console.log(Date.now()-t0); }
|
实现平行加速
promise没有按顺序执行,但是await按顺序接收到每个promise的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| async function randomDelay(id){ const delay=Math.random()*1000; return new Promise((resolve)=>setTimeout(()=>{ console.log(`${id} finished`); resolve() },delay)) } async function foo(){ const t0=Date.now() const p0=randomDelay(0); const p1=randomDelay(1); const p2=randomDelay(2); const p3=randomDelay(3); await p0; await p1; await p2; await p3; setTimeout(console.log,0,`${Date.now()-t0} ms elapsed`) } foo();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| async function randomDelay(id){ const delay=Math.random()*1000; return new Promise((resolve)=>setTimeout(()=>{ console.log(`${id} finished`); resolve(id) },delay)) } async function foo(){ const t0=Date.now() const promises=Array(5).fill(null).map((key,index)=>randomDelay(index)); for(const p of promises){ console.log(`awaited ${await p}`) } setTimeout(console.log,0,`${Date.now()-t0} ms elapsed`) } foo();
|
Promise.all原理
只有传入的所有Promise都完成,返回promise才能完成,如果有任何promise被拒绝,返回的主promise就立即拒绝(抛弃任何其他promise的结果),如果全部完成,你会得到一个数组,其中包含传入的所有promise的完成值,对于拒绝的情况,你只会的到第一个拒绝promise的拒绝理由值,这种模式成为门,所有人到齐了才开门,传入空数组会立即完成
1 2 3 4 5 6 7 8 9 10 11 12 13
| Promise.all=function(promises){ const res=[]; return new Promise((resolve,reject)=>{ promises.forEach(promise=>{ promise.then((value,index)=>{ res[idx]=value; if(res.length==promises.length){ resolve(res) } },reason=>reject(reason)) }) }) }
|
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function runAsync (x) { const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000)) return p } function runReject (x) { const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)) return p } Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]) .then(res => console.log(res)) .catch(err => console.log(err))
1 3
2 Error: 2
4
|
Promise.race():
只有第一个决议的promise取胜,并且决议结果成为返回promise的决议。其他任务虽然会继续进行,但是race已经不管那些任务的结果了,不能传入空数组,传入空数组promise.race()会挂住,且永远不会决议
1 2 3 4 5 6 7 8 9 10 11
| function runAsync (x) { const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000)) return p } Promise.race([runAsync(1), runAsync(2), runAsync(3)]) .then(res => console.log('result: ', res)) .catch(err => console.log(err))
'result: ' 1 2 3
|
Promise.race()原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Promise.race=function(promises){ promises=Array.from(promises); return new Promise((resolve,reject)=>{ if(promises.length===0){ return; } else{ for(let i=0;i<promises.length;i++){ Promise.resolve(promises[i]).then((data)=>{ resolve(data); return; },(err)=>{ reject(err); return; }) } }
}) }
|
Promise.resolve()原理
1 2 3 4 5 6 7 8 9 10 11 12 13
| Promsie.resolve=function(param){ if(param instanceof Promise)return param; return new Promise((resolve,reject)=>{ if(param &&typeof param==='object'&& typeof param.then==='function'){ setTimeout(()=>{ param.then(resolve,reject); }) }else{ resolve(param) } }) }
|
Promise.reject()
1 2 3 4 5
| Promise.reject=function(reason){ return new Promise((resolve,reject)=>{ return reject(reason) }) }
|
Promise.catch()
1 2 3
| Promsie.prototype.catch=function(onRejected){ return this.then(null,onRejected); }
|
Promise.finally():
1 2 3 4 5 6 7 8 9 10 11
| Promise.prototype.finally=function(cb){ return this.then((value)=>{ return Promise.resolve(callback).then(()=>{ return value; }) },(err)=>{ return Promise.resolve(callback).then(()=>{ throw err; }) }) }
|
每隔一秒打印1,2,3
1 2 3
| const arr=[1,2,3]; arr.reduce( (p,x)=>p.then(()=>new Promise(resolve=>setTimeout(()=>resolve(console.log(x)),1000))),Promise.resolve())
|
一秒后打印出1,2,3
1 2 3
| arr.reduce( (p,x)=>p.then(new Promise(resolve=>setTimeout(resolve(console.log(x)),1000))),Promise.resolve() )
|
红绿灯交替闪烁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| function red(){ console.log("red") } function yellow(){ console.log("yellow") } function green(){ console.log("green") } const light=(time,cb)=>{ return new Promise(resolve=>{ setTimeout(()=>{ cb(); resolve(); },time) })
} const step=function(){ Promise.resolve() .then(()=>{ return light(3000,red) }) .then(()=>{ return light(2000,yellow) }) .then(()=>{ return light(1000,green) })} step();
|
mergepromise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const time = (timer) => { return new Promise(resolve => { setTimeout(() => { resolve() }, timer) }) } const ajax1 = () => time(2000).then(() => { console.log(1); return 1 }) const ajax2 = () => time(1000).then(() => { console.log(2); return 2 }) const ajax3 = () => time(1000).then(() => { console.log(3); return 3 })
function mergePromise (promises) { let data=[] let promise=Promise.resolve(); promises.forEach(ajax=>{ promise=promise.then(ajax).then(res=>{data.push(res);return data}) }) return promise; }
mergePromise([ajax1, ajax2, ajax3]).then(data => { console.log("done"); console.log(data); });
|
异步加载图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| function loadImage(url){ return new Promise((resolve,reject)=>{ const img=new Image(); img.onload=function(){ console.log("一张图片加载完成") resolve(img) } img.onerror=function(){ reject(new Error("Cannot load"+url)); } img.src=url; }) } var urls = [ "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png", ]; function limitedLoad(urls,handler,limit){ let sequence=[...urls]; let promises=sequence.splice(0,limit).map((url,index)=>{ return handler(url).then(index=>{ return index; }) }) return sequence.reduce( (p,url)=>{ return p.then(()=>{return Promise.race(promises)}) .then(fastIndex=>{promises[fastIndex]=handler(url).then(()=>{return fastIndex})}) .catch(err=>{console.error(err)}) },Promise.resolve()) .then(()=>{return Promise.all(promises)})
} limitedLoad(urls,loadImage,3) .then(res=>{ console.log("图片全部加载完成") console.log(res) }) .catch(err=>{ console.error(err) })
|
判断图片是否加载延迟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function loadImage(url){ return new Promise((resolve,reject)=>{ const img=new Image(); img.onload=function(){ console.log("一张图片加载完成") resolve(img) } img.onerror=function(){ reject(new Error("Cannot load"+url)); } img.src=url; }) } function timeout(){ var p=new promise((resolve,reject)=>{ setTimeout(()=>{ reject('图片超时') },5000) }) } Promise.race([loadImage(),timeout()]).then((data)=>{ console.log(data); }).catch((err)=>{ console.log(err) })
|