假设我有一组promise正在发出网络请求,其中一个将失败:
// http://does-not-exist will throw a TypeError
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]
Promise.all(arr)
.then(res => console.log('success', res))
.catch(err => console.log('error', err)) // This is executed
假设我想要等到所有这些都完成,不管是否有一个失败了。可能有一个资源的网络错误,我可以没有,但如果我能得到,我想在继续之前。我想优雅地处理网络故障。
因为承诺。所有这些都没有留下任何空间,在不使用承诺库的情况下,处理这个问题的推荐模式是什么?
类似的答案,但更适合ES6:
const a = Promise.resolve(1);
const b =承诺。拒绝(新的错误(2));
const c = Promise.resolve(3);
的承诺。[a, b, c]。(p => p.catch(e => e)))
.then(results => console.log(results)) // 1,错误:2,3
.catch(e => console.log(e));
const console = {log: msg => div.innerHTML += msg + "<br>"};
< div id = " div " > < / div >
根据返回值的类型,通常可以很容易地区分错误(例如,用undefined表示“don't care”,用typeof表示普通的非对象值,用result。result.toString(). startswith ("Error:")等
这是我的custom settdpromiseall ()
const settledPromiseAll = function(promisesArray) {
var savedError;
const saveFirstError = function(error) {
if (!savedError) savedError = error;
};
const handleErrors = function(value) {
return Promise.resolve(value).catch(saveFirstError);
};
const allSettled = Promise.all(promisesArray.map(handleErrors));
return allSettled.then(function(resolvedPromises) {
if (savedError) throw savedError;
return resolvedPromises;
});
};
与Promise.all相比
如果所有的承诺都得到了解决,那么它的性能与标准承诺完全相同。
如果多个promise中有一个被拒绝,它返回第一个被拒绝的promise,与标准的promise大致相同,但不同的是,它等待所有的promise都被解决/拒绝。
为了勇敢,我们可以改变。
(function() {
var stdAll = Promise.all;
Promise.all = function(values, wait) {
if(!wait)
return stdAll.call(Promise, values);
return settledPromiseAll(values);
}
})();
小心。一般来说,我们从不改变内置程序,因为这可能会破坏其他不相关的JS库,或者与未来对JS标准的更改发生冲突。
我的承诺是向后兼容的承诺。并扩展其功能。
开发标准的人——为什么不将其包含到新的Promise标准中呢?
我也遇到过同样的问题,我用下面的方法解决了这个问题:
const fetch = (url) => {
return node-fetch(url)
.then(result => result.json())
.catch((e) => {
return new Promise((resolve) => setTimeout(() => resolve(fetch(url)), timeout));
});
};
tasks = [fetch(url1), fetch(url2) ....];
Promise.all(tasks).then(......)
那样的话,答应我。所有人都在等待每一个承诺都将进入解决或拒绝的状态。
有了这个解决方案,我们以一种非阻塞的方式“停止捕获执行”。事实上,我们并没有停止任何事情,我们只是返回处于挂起状态的Promise,当它在超时后被解决时,它会返回另一个Promise。
从ES5开始,我一直在使用以下代码。
Promise.wait = function(promiseQueue){
if( !Array.isArray(promiseQueue) ){
return Promise.reject('Given parameter is not an array!');
}
if( promiseQueue.length === 0 ){
return Promise.resolve([]);
}
return new Promise((resolve, reject) =>{
let _pQueue=[], _rQueue=[], _readyCount=false;
promiseQueue.forEach((_promise, idx) =>{
// Create a status info object
_rQueue.push({rejected:false, seq:idx, result:null});
_pQueue.push(Promise.resolve(_promise));
});
_pQueue.forEach((_promise, idx)=>{
let item = _rQueue[idx];
_promise.then(
(result)=>{
item.resolved = true;
item.result = result;
},
(error)=>{
item.resolved = false;
item.result = error;
}
).then(()=>{
_readyCount++;
if ( _rQueue.length === _readyCount ) {
let result = true;
_rQueue.forEach((item)=>{result=result&&item.resolved;});
(result?resolve:reject)(_rQueue);
}
});
});
});
};
用法签名就像Promise.all。主要的区别在于《承诺》。等待会等待所有的承诺来完成自己的工作。