原文地点: https://www.xiabingbao.com/po…
本篇文章主如果想经由过程ES6中Promise供应的几个要领,来完成诸如first、last、none、any等种种变体要领!
在范例的ES6范例中,供应了Promise.all
和Promise.race
两种,我们起首来了解下这两个要领是干吗的,轻易我们背面事情的睁开。Promise.all中一切的Promise实例都处于完成状况,该要领才进入完成状况,不然恣意一个被谢绝,则该要领进入谢绝状况,并舍弃其他一切完成的结果,谢绝缘由是第一个被谢绝的实例的缘由。Promise.race中恣意的一个Promise实例变成完成状况或许谢绝状况,则race完毕,race的结果即为第一个变成终究状况的结果!更细致的能够参考下阮一峰的文章Promise对象之Promise.all。
1. 准备事情
在最先编写种种变体要领之前,这里我们起首定义几个一会儿要运用的几个Promise实例:
/**
* 建立一个Promise对象的实例
* @param name {string} 该实例的称号
* @param flag {boolean} 返回的结果状况:完成照样谢绝
* @param diff {number} 耽误的时候
*/
var createPromiseCase = ( name, flag, diff ) => {
return new Promise( ( resolve, reject ) => {
setTimeout( () => {
flag ? resolve( name ) : reject( new Error( 'testPromise is error, name: ' + name ) );
}, diff );
} );
};
var p1_suc_100 = createPromiseCase( 'p1-suc-100', true, 100 );
var p2_suc_500 = createPromiseCase( 'p2-suc-500', true, 500 );
var p3_suc_300 = createPromiseCase( 'p3-suc-300', true, 300 );
var p4_fail_400 = createPromiseCase( 'p4-fail-400', false, 400 );
var p5_fail_200 = createPromiseCase( 'p5-fail-200', false, 200 );
2. 种种变体要领
2.1 Promise.first
场景:一个页面当前正处于loading状况,同时要求了多个接口,不管哪一个接口准确返回结果,则loading结果作废!或许其他的要猎取猎取第一个完成状况的值。
这里就要用到了Promise.first
了,只需恣意一个Promise实例变成完成状况,则Promise.first变成完成状况。实在这里并不合适Promise.race
要领,由于第一个变成谢绝状况的实例也会激活Promise.race,
if ( !Promise.first ) {
// get first resolve result
Promise.first = promiseList => {
return new Promise( ( resolve, reject ) => {
var num = 0;
var len = promiseList.length;
promiseList.forEach( pms => {
Promise.resolve( pms ).then( resolve ).catch( () => {
num++;
if ( num === len ) {
reject( 'all promises not resolve' );
}
} );
} );
} );
};
}
挪用体式格局:
Promise.first([p4_fail_400, p2_suc_500, p3_suc_300])
.then(res => console.log(res)) // p3-suc-300
.catch(e => console.error(e))
能够看到每次猎取的p3_suc_300的值,由于p4是失利的状况,p2的完成状况没有p3快,因而这里猎取到了p3的结果。
2.2 Promise.last
与Promise.first对应的则是Promise.last
,猎取末了变成完成状况的值。这里与Promise.first差别的是,只要末了一个Promise都变成终究态(完成或谢绝),才晓得哪一个是末了一个完成的,这里我采用了计数的体式格局,then
和catch
只能二选一,等计数器到达list.length时,实行外部的resolve。
if ( !Promise.last ) {
// get last resolve result
Promise.last = promiseList => {
return new Promise( (resolve, reject) => {
let num = 0;
let len = promiseList.length;
let lastResolvedResult;
const fn = () => {
if (++num===len) {
lastResolvedResult ? resolve(lastResolvedResult) : reject('all promises rejected');
}
}
promiseList.forEach( pms => {
Promise.resolve( pms )
.then(res => {
lastResolvedResult = res;
fn()
})
.catch(fn);
} )
} )
}
}
挪用体式格局:
Promise.last([p1_suc_100, p2_suc_500, p5_fail_200, p3_suc_300, p4_fail_400])
.then(res => console.log(res)) // p2-suc-500
.catch(e => console.error(e))
p2须要500ms才完成,是最晚完成的。
2.3 Promise.none
Promise.none
与Promise.all恰好相反,一切的promise都被谢绝了,则Promise.none变成完成状况。该要领能够用Promise.first来切换,当实行Promise.first的catch时,则实行Promise.none中的resolve。不过这里我们运用Promise.all来完成。
if ( !Promise.none ) {
// if all the promises rejected, then succes
Promise.none = promiseList => {
return Promise.all( promiseList.map( pms => {
return new Promise( ( resolve, reject ) => {
// 将pms的resolve和reject反过来
return Promise.resolve( pms ).then( reject, resolve );
} )
} ) )
}
}
挪用体式格局:
Promise.none([p5_fail_200, p4_fail_400])
.then(res => console.log(res))
.catch(e => console.error(e))
// then的输出结果:
// [
// Error: testPromise is error, name: p5-fail-200,
// Error: testPromise is error, name: p4-fail-400
// ]
两个promise都失利后,则Promise.none进入完成状况。
2.4 Promise.any
Promise.any示意只猎取一切的promise中进入完成状况的结果,被谢绝的则疏忽掉。
if ( !Promise.any ) {
// get only resolve the results
Promise.any = promiseList => {
let result = [];
return Promise.all( promiseList.map( pms => {
return Promise.resolve( pms )
.then( res => result.push( res ) )
.catch( e => { } );
} ) ).then( ( res ) => {
return new Promise( ( resolve, reject ) => {
result.length ? resolve( result ) : reject();
} )
} )
}
}
挪用体式格局:
Promise.any([p1_suc_100, p2_suc_500, p5_fail_200, p3_suc_300, p4_fail_400])
.then(res => console.log(res)) // ["p1-suc-100", "p3-suc-300", "p2-suc-500"]
.catch(e => console.error(e))
2.5 Promise.every
末了一个的完成比较简单,一切的promise都进入完成状况,则返回true,不然返回false。
if (!Promise.every) {
// get the boolean if all promises resolved
Promise.every = promiseList => {
return Promise.all(promiseList)
.then(() => Promise.resolve(true))
.catch(() => Promise.resolve(false));
}
}
挪用体式格局:
Promise.every([p1_suc_100, p2_suc_500, p3_suc_300])
.then(result => console.log('Promise.every', result)); // Promise.every true
Promise.every([p1_suc_100, p4_fail_400])
.then(result => console.log('Promise.every', result)); // Promise.every false
3. 总结
Promise另有种种方面的运用,许多类库也都完成了相似的要领,这里也仅仅是鄙人鄙见,轻微完成了Promise的变体要领,加深下对Promise的明白。
原文地点: 蚊子的博客