Comments (42)
function http(value, flag){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
if(Math.random() < 0.5){ // 设定一个成功或者失败的条件
resolve(value)
console.log(flag?'重新请求成功':'第一次请求成功',value)
}else{
console.log(flag?'重新请求失败':'第一次请求失败',value)
resolve(http(value,true))
}
}, Math.random()*2000)
})
}
let A = http('A');
let B = http('B');
let C = http('C');
let D = http('D');
Promise.all([A,B,C,D]).then(res=>{
console.log('成功',res)
})
from all-of-frontend.
请求失败自动重传机制
使用 tryRequest 方法将异步请求(promise)包裹,如果请求失败(reject)并且小于尝试次数,将自动尝试再次请求。
/*
* @description 失败重试
* @param request Promise 对象
* @param times 设置的总尝试次数
* @param time 第几次
*/
function tryRequest(request, times = 0, time = 1) {
return request().catch(e => {
if (time <= times) {
console.log(e.message, `第${time}次重试`)
return tryRequest(request, times, ++time)
} else {
return Promise.reject(e)
}
})
}
// 创建模拟请求
function creatMockRequest(name) {
return () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(`${name} success`)
} else {
reject(new Error(`${name} error`))
}
}, Math.random * 1000)
})
}
}
let requests = ['A', 'B', 'C', 'D'].map(item => {
return tryRequest(creatMockRequest(item), 3)
})
Promise.all(requests).then(res => {
console.log('成功了:', res)
}).catch(e => {
console.log('失败了:', e.message)
})
from all-of-frontend.
感觉这道题没啥意思
from all-of-frontend.
源码:
/**
* Desc: Promise all 错误处理
* Date: 2021-03-12
* Author: Akimto
* 异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试。
Promise.all([A, B, C, D])
4 个请求完成后发现 AD 请求失败了,如果让 AD 请求重试
*/
export class PromiseAll {
private retryTimes: number = 3;
/**
* 模拟延迟
* @param time 延迟时间 秒
* @returns
*/
private sleep(time: time): Promise<any> {
return new Promise<any>(resolve => {
setTimeout(() => {
resolve(null);
}, time * 1000);
});
}
private postRequest(param: string) {
return new Promise(async resolve => {
let retryTimes = this.retryTimes;
const request = async (param: any) => {
const requestDelay = Math.random() * 2;
//模拟请求延迟和请求失败
await this.sleep(requestDelay);
let resMsg = ``;
const isFailed = (param === "A" || param === "D");
if (isFailed) {
resMsg = `请求:${param} 失败 重试次数: ${this.retryTimes - retryTimes} 耗时: ${requestDelay.toFixed(2)}ms`;
if (retryTimes > 0) {
retryTimes--;
console.log(`${param} retryTimes: ${retryTimes}`);
request(param);
} else {
resolve(resMsg);
}
} else {
resMsg = `请求:${param} 成功 耗时: ${requestDelay.toFixed(2)}ms`;
resolve(resMsg);
}
}
request(param);
});
}
public async main() {
console.log("main");
const requestA = this.postRequest("A");
const requestB = this.postRequest("B");
const requestC = this.postRequest("C");
const requestD = this.postRequest("D");
await Promise.all([requestA, requestB, requestC, requestD]).then(result => {
console.log(result);
}).catch(error => {
console.error(error);
});
console.log("finished");
}
}
const promiseAll = new PromiseAll();
promiseAll.main();
from all-of-frontend.
let rejarr = [];
const httprequest = function (type, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() * 1000 > time
? resolve(type)
: reject({ type, time });
}, time);
}).catch((rej) => {
rejarr.push(httprequest(rej.type, rej.time));
});
};
let p1 = httprequest("A", Math.random() * 1000);
let p2 = httprequest("B", Math.random() * 1000);
let p3 = httprequest("C", Math.random() * 1000);
let p4 = httprequest("D", Math.random() * 1000);
let all = (arr) => {
Promise.all(arr).then((res) => {
if (rejarr.length) {
all(rejarr);
rejarr = [];
}
});
};
all([p1, p2, p3, p4]);
from all-of-frontend.
// 模拟第一次请求失败
const error = {
A: true,
D: true
};
function getData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟第一次请求失败
if (error[url]) {
error[url] = false;
reject(url);
} else {
resolve(url);
}
}, 0);
});
}
function retryRequest(promise, retryNum) {
return new Promise((resolve, reject) => {
promise()
.then((data) => resolve(data))
.catch((error) => {
if (retryNum > 0) {
retryRequest(promise, retryNum - 1);
} else {
reject(error);
}
});
});
}
function handleAll() {
return new Promise((resolve, reject) => {
Promise.all([getData("A"), getData("B"), getData("C"), getData("D")])
.then((data) => {
console.log("请求返回的结果", data);
resolve(data);
})
.catch((error) => {
console.log(`${error}, 请求失败,开始重试`);
reject(error);
});
});
}
retryRequest(handleAll, 1);
from all-of-frontend.
const requestInterface =
(name, time, isSuccess) =>
new Promise((resolve, reject) => {
setTimeout((name) => {
isSuccess ? resolve(name) : reject()
}, time, name)
}).catch(err => requestInterface(name, time, true))
const A = requestInterface('A', 500, false)
const B = requestInterface('B', 1000, true)
const C = requestInterface('C', 1500, true)
const D = requestInterface('D', 800, false)
Promise.all([A, B, C, D])
.then((params) => void console.log('成功', params))
.catch(error => void console.log('失败', error))
from all-of-frontend.
promise.all
这个Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。
失败/拒绝(Rejection):
如果传入的 promise 中有一个失败(rejected),Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成。
function wait(duration) {
return new Promise((resolve) => setTimeout(resolve, duration * 1000));
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
async function requestB(name) {
await wait(getRandomIntInclusive(1, 5));
try {
if (getRandomIntInclusive(1, 5) > 2) {
throw `${name} function wrong`;
}
return new Promise((resolve) => resolve(name));
} catch (error) {
console.log("requestB error", error);
console.log(`function ${name} retry`);
return requestB(name);
}
}
async function doFunB(functionName) {
console.log(`doFunB start ${functionName}`);
return await requestB(functionName);
}
async function testB() {
const res = await Promise.all([
doFunB("A"),
doFunB("B"),
doFunB("C"),
doFunB("D"),
]);
console.log("res", res);
}
testB();
结果
[Running] node "e:\coding\inspiration-git\vite-vue3\tempCodeRunnerFile.javascript"
doFunB start A
doFunB start B
doFunB start C
doFunB start D
requestB error A function wrong
function A retry
requestB error D function wrong
function D retry
res [ 'A', 'B', 'C', 'D' ]
[Done] exited with code=0 in 5.13 seconds
from all-of-frontend.
//经过一层包装把失败请求的返回回去
async function allError(p) {
try {
const res = await p
return 0
}catch(e) {
return p
}
}
Promise.all([A, B, C, D].map(item => allError(item))).then(arr => {
const item = arr.filter(list => list !== 0)
if(item && item.length) {
Promise.all(item).then(() => {
console.log('又试一次成功了')
})
}
}).catch(err => {
console.log(err)
})
from all-of-frontend.
待完善的优化
对于失败的请求,目前使用index作为固定的标识,只会重复请求多一次
var index = -1; // 模拟下标0和2请求失败,失败的请求只重复请求多一次
var failArr = []; // 记录失败的请求
function Request(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
index++;
if (index === 0 || index === 2) {
console.log("失败", name);
reject(name);
} else {
console.log("成功", name);
resolve(name);
}
}, randomTime());
}).catch(e => {
console.log("promise catch", e);
failArr.push(name);
});
}
function randomTime() {
return Math.round(Math.random() * 1000);
}
// Test:异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试。
function Test() {
Promise.all([Request('A'), Request('B'), Request('C'), Request('D')]).then(res => {
failArr.forEach((item, index) => {
Request(item);
});
}).catch(e => {
console.log("promiseAll Error", e);
});
}
Test();
from all-of-frontend.
function mockHttp(str, time = 0.5, flag = false) {
return new Promise((resolve, reject) => {
let isSuccess = flag || Math.random() > 0.5
setTimeout(() => {
console.log('mockHttp str, isSuccess -> ', str, isSuccess);
isSuccess ? resolve(str) : reject();
}, time * 1000);
});
}
Promise.all([
mockHttp('A').catch(() => mockHttp('A', true)),
mockHttp('B').catch(() => mockHttp('B', true)),
mockHttp('C').catch(() => mockHttp('C', true)),
mockHttp('D').catch(() => mockHttp('D', true)),
]).then(res => {
console.log(res);
})
from all-of-frontend.
// 异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试。
// Promise.all([A, B, C, D])
// 4 个请求完成后发现 AD 请求失败了,如果让 AD 请求重试
function request(name, count = 0) {
return new Promise((resolve, reject) => {
const isSuccess = Math.random() > 0.5;
console.log(`接口${name}: ${isSuccess}`);
setTimeout(() => {
isSuccess > 0.5 ? resolve(name) : reject(name);
}, Math.random() * 1000);
}).catch((err) => {
count++;
if (count > 2) {
return Promise.reject(`后端大爷${name}接口写的666`);
}
return request(name, count);
});
}
let queue = [request('A'), request('B'), request('C'), request('D')];
Promise.all(queue)
.then((arr) => {
console.log(arr);
})
.catch((err) => {
console.log(err);
});
from all-of-frontend.
function retryRequest (arr = []) {
Promise.all(arr).then(res => {
console.log('成功', res)
}).catch(err => {
console.log('失败', err)
})
}
function getRandomTime() {
return Math.ceil(Math.random() * 2000) + 100
}
function request (data) {
return new Promise((resolve, reject) => {
const time = getRandomTime()
setTimeout(() => {
if (time > 1000) {
resolve(data)
} else {
reject(data)
}
}, time)
}).catch(err => {
return request(data)
})
}
retryRequest([request('A'), request('B'), request('C'), request('D')])
from all-of-frontend.
function http (value, flag) {
return new Promise((r, j) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) { // 设定一个成功或者失败的条件
resolve(value)
} else {
reject(value)
}
}, Math.random() * 2000)
}).then((val) => {
console.log(flag ? '重新请求成功' : '第一次请求成功', value)
r(val)
}, (rejVal) => { // 失败的请求,再次调用;
console.log(flag ? '重新请求失败' : '第一次请求失败', value)
r(http(rejVal, true))
})
})
}
let A = http('A');
let B = http('B');
let C = http('C');
let D = http('D');
Promise.all([A, B, C, D]).then(res => {
console.log('成功', res)
})
from all-of-frontend.
let rejectArr = []
function request(value) {
return new Promise((resolve, reject)=> {
if (成功)
resolve(value)
else(失败)
reject(value)
}).then(data=> {})
.catch(err) {
rejectArr.push(request(err.value))
}
}
let _promiseAll = function(arr) {
return Promise.all(arr).then((res)=> {
if(rejectArr.length) {
_promiseAll(rejectArr);
rejectArr = []
}
})
}
from all-of-frontend.
/**
* 异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试。
* Promise.all([A, B, C, D])
* 4 个请求完成后发现 AD 请求失败了,如何让 AD 请求重试
*/
const failedList = [];
const fetchData = (params) => {
return new Promise((resolve, reject) => {
response(params, resolve, reject);
}).catch((error) => {
// 这里的 error 其实就是 reject 过来的 parmas
failedList.push(fetchData(error));
});
};
// 模拟数据返回,有一定的几率失败
const response = (params, resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.6) {
console.log(params + "执行失败,重试");
reject(params);
} else {
console.log(params + "执行成功");
resolve(params);
}
}, Math.random() * 2000);
};
const promiseList = [
fetchData("A"),
fetchData("B"),
fetchData("C"),
fetchData("D"),
];
let result = [];
const getPromiseAll = (arr) => {
Promise.all(arr).then((res) => {
result = result.concat(res);
// 检查失败队列是否有失败的任务
if (failedList.length > 0) {
getPromiseAll(failedList);
failedList.length = 0;
} else {
console.log(result.filter((item) => item !== undefined));
}
});
};
getPromiseAll(promiseList);
from all-of-frontend.
const request = function (type, isSuccess) {
console.log(isSuccess, type);
return new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) {
resolve(type);
} else {
reject(type);
}
}, 1000);
}).catch((rej) => {
request(rej, true);
});
};
let A = request("A", false);
let B = request("B", true);
let C = request("C", false);
let D = request("D", true);
Promise.all([A, B, C, D])
.then((res) => {
console.log("成功", res);
})
.catch((rej) => {
console.log("失败", rej);
});
from all-of-frontend.
let errReq=[];
let A = Promise.reject('A').catch(err=>{errReq.push(err);});
let B = Promise.resolve('B').catch(err=>{errReq.push(err);});
let C = Promise.resolve('C').catch(err=>{errReq.push(err);});
let D = Promise.reject('D').catch(err=>{errReq.push(err);});
Promise.all([A,B,C,D]).then(res => {
res.forEach(e=>{
console.log(!e?e+':请求失败!':e+':请求成功!')
});
if(errReq && errReq.length>0){
errReq.forEach((e)=>{
Promise.resolve(e).then(res=>{ console.log("二次请求"+res+"---成功");});
})
}
});
from all-of-frontend.
let failedList = [];
function getData(apiName, index) {
if (index === 0) {
failedList = []
}
return new Promise((resolve, reject) => {
var time = Math.random() > 0.5 // 模拟请求成功、失败
if (time) {
resolve(`${apiName} 请求成功`)
} else {
failedList.push(apiName)
resolve(`${apiName} 请求失败`)
}
})
}
let curRequestCount = 1 // 当前请求次数
let maxRequestCount = 3 // 最大重试次数
let curruntFailedList = []
function sendRequest(again) {
var promiseList = again ? curruntFailedList.map((item, index) => getData(item, index)) : ['A', 'B', 'C', 'D'].map(item => getData(item))
return Promise.all(promiseList).then(values => {
values.map((item, index) => {
console.log(item)
})
curruntFailedList = failedList
if (failedList.length > 0 && curRequestCount < maxRequestCount) {
console.log('下一次执行准备....')
++curRequestCount
sendRequest(true)
} else {
return
}
}).catch(error => {
debugger
})
}
sendRequest()
from all-of-frontend.
let requestList = {
A: true,
B: true,
C: false,
D: true
}
function request(key, res){
let p = new Promise((resolve, reject) => {
if(res) {
// 如果请求成功就将请求从待请求对象中去除
console.log('resolve', key)
resolve(key)
delete requestList[key]
}
else {
// 请求失败则保留请求在待请求对象中
console.log('reject', key)
reject(key)
}
})
return p
}
function retry(times = 5){
return Promise.all(Object.keys(requestList).map(key => {
let res = requestList[key]
return request(key, res)
})).then(res => {
return 'success'
}).catch(err => {
if(times >= 1) return retry(times - 1)
else throw('fail')
})
}
retry().then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
输出
resolve A
resolve B
reject C
resolve D
reject C
reject C
reject C
reject C
reject C
fail
from all-of-frontend.
let fail = []
let request = function(val, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (time < 1000) {
resolve(val)
} else {
reject(val)
}
}, time)
}).catch(data => {
console.log(data,'1')
return request(data, 500)
})
}
let A = request('A', 1100)
let B = request('B', 100)
let C = request('C', 500)
let D = request('D', 1100)
Promise.all([A,B,C,D]).then((val) => {
console.log(val, '成功')
})
from all-of-frontend.
function simulateRequest(value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() * 10 > 5) {
console.log('resolve', value);
resolve(value);
} else {
console.log('reject', value);
reject(value);
}
}, Math.floor(Math.random() * 1000));
}).catch(e => {
console.log(e, ';');
simulateRequest(e);
});
}
function allSettled(fn) {
Promise.all(fn).then(res => {
console.log(res);
});
}
const p1 = simulateRequest('A');
const p2 = simulateRequest('B');
const p3 = simulateRequest('C');
const p4 = simulateRequest('D');
const fn = [p1, p2, p3, p4];
本来是想用promise.allSettled来做的,但是好像和这个的使用场景稍微有些区别,还得再去看看两者的使用场景
from all-of-frontend.
let fn5 = function (params, count = 0) {
return new Promise((resolve, reject) => {
let time = Math.random() * 1000
const isSuccess = time < 0.5 * 1000
setTimeout(() => {
if (isSuccess) {
console.log(${params}${count?'重新':''}请求成功
)
resolve(params)
} else {
reject(params)
}
},time)
}).catch((err) => {
console.log(${err}${count?'重新':''}请求失败
)
if (count < 1) {
return fn5(err, 1)
}
return ''
})
}
let arr5 = ['A', 'B', 'C', 'D'].map(item => {
return fn5(item)
})
Promise.all(arr5).then(data => {
console.log('fn5:', data)
})
from all-of-frontend.
MDN解释: Promise.all()方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个Promise实例, 那个输入的所有promise的resolve回调的结果是一个数组。这个Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。
return new Promise((resolve, reject) => {
// 模拟异步请求
setTimeout(() => {
// 模拟请求结果
if (Math.random() > 0.5) {
// 如果请求成功则调用resolve
resolve(value);
// 使用flag来判断是第一次请求还是重新发起的请求
console.log(flag ? "重新请求成功" : "第一次请求成功", value);
} else {
// 请求失败会打印哪个请求报的错,并且执行resolve再次发送请求
console.log(flag ? "重新请求失败" : "第一次请求失败", value);
resolve(sendPost(value, true));
}
}, Math.random() * 2000);
});
}
let A = sendPost("A");
let B = sendPost("B");
let C = sendPost("C");
let D = sendPost("D");
Promise.all([A, B, C, D]).then((res) => {
console.log("全部请求成功", res);
});
// 执行结果
// 第一次请求成功 B
// 第一次请求失败 D
// 重新请求失败 D
// 第一次请求成功 A
// 第一次请求失败 C
// 重新请求失败 D
// 重新请求成功 C
// 重新请求成功 D
// 全部请求成功 [ 'A', 'B', 'C', 'D' ]
from all-of-frontend.
let req = function(data){
return new Promise((reslove,reject)=>{
//定义这里0.5以上为请求ok
if(Math.random()>0.5){
console.log(`${data}请求成功`);
reslove(data);
}else{
reject(data);
}
}).catch((rej)=>{
console.log(`${rej}请求失败,将重新发起`);
return req(rej);
})
}
Promise.all([req('a'),req('b'),req('c')]).then((res)=>{
console.log(`请求结束 ${res}`)
})
from all-of-frontend.
// 参考了上面大兄弟的代码
const httpRequest = (tag, times = 3) =>
new Promise((resolve, reject) => {
const fn =
Math.random() > 0.5
? () => resolve(tag)
: () => reject({ tag, times: times - 1 })
setTimeout(fn, parseInt(Math.random() * 1000), 10)
}).catch(({ tag, times }) => {
if (times > 0) {
console.log(`${tag} 重试中...`)
return httpRequest(tag, times)
}
return Promise.resolve()
})
const test = async () => {
const httpRequestArr = "ABCDEF".split("").map((item) => httpRequest(item, 3))
const res = await Promise.all(httpRequestArr)
console.log(res)
}
test()
from all-of-frontend.
function request(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(Math.random() > 0.5) {
reject()
} else {
result.set(params, params)
resolve(params)
}
}, Math.random() * 2000)
})
.catch(() => {
// 如果请求失败在这里打个标记
return 'error'
})
}
let requestList = ['A','B','C','D']
let result = new Map()
let currTimes = 1
function handleRequestList(paramsArr) {
if(currTimes === 1) {
paramsArr.forEach(item => {
result.set(item, '')
})
}
let requestList = paramsArr.map(params => {
return request(params)
})
Promise.all(requestList)
.then(res => {
// 筛选出失败的请求
let failRes = []
res.forEach((item,index) => {
if(item === 'error') failRes.push(paramsArr[index]);
})
console.log(`这是第${currTimes}次请求`)
if(failRes.length === 0) {
// 没有请求失败的
console.log('所有请求成功, 最终结果是', Array.from(result.values()))
currTimes = 1
result = []
} else {
// 有请求失败的
currTimes++
console.log('存在请求失败,稍后重试, 当前结果为', Array.from(result.values()))
//重新请求
handleRequestList(failRes)
}
})
}
handleRequestList(requestList)
PS C:\Users\Y_D\Desktop\daka> node index.js
这是第1次请求
存在请求失败,稍后重试, 当前结果为 [ 'A', '', '', 'D' ]
这是第2次请求
所有请求成功, 最终结果是 [ 'A', 'B', 'C', 'D' ]
from all-of-frontend.
let errPromise: any[] = [];
const promiseError = (name: string, time = 3000) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(`error${name}`);
}, time * Math.random())
}).catch(error => {
if (error.indexOf(name) > -1) {
errPromise.push(promiseRight(name));
}
})
};
const promiseRight = (name: string, time = 4000) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(name);
}, time * Math.random())
});
};
const all = (promiseArray: any[]) => {
Promise.all(promiseArray).then(res => {
console.log(res, 'eeeee');
// 这里判断一下完成没
if (res.length !== errPromise.length && errPromise.length) {
all(errPromise)
}
}).catch(err => {
console.error(err, 'err')
})
}
all([promiseError('A'), promiseRight('B'), promiseRight('c'), promiseError('D')]);
测试结果
[undefined, "B", "c", undefined] "eeeee"
["A", "D"] "eeeee"
from all-of-frontend.
参考了网上的答案 并测试了其它几种情况
// Promise.all(task).then().catch() 会在所有task都resolve时才会进then方法,
// 并且把所有结果以一个数组返回。只要有一个失败,就会进catch。
// 但如果在单个请求中定义了catch方法,就不会进Promise.all的catch方法。
因此,可以在单个的catch中将失败的promise放入一个list,待一轮请求完成后,再去请求失败的请求。
function http(value, flag) {
return new Promise((r, j) => {
setTimeout(() => {
if (Math.random() < 0.5) { // 设定一个成功或者失败的条件
r(value)
} else {
j(value)
}
}, Math.random() * 2000)
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// if (Math.random() < 0.5) { // 设定一个成功或者失败的条件
// resolve(value)
// } else {
// reject(value)
// }
// }, Math.random() * 2000)
// }).then((val) => `{`
// console.log(flag ? '重新请求成功' : '第一次请求成功', value)
// r(val)
// }, (rejVal) => { // 失败的请求,再次调用;
// console.log(flag ? '重新请求失败' : '第一次请求失败', value)
// r(http(rejVal, true))
// })
})
}
let A = http('A');
let B = http('B');
let C = http('C');
let D = http('D');
Promise.all([A, B, C, D]).then(res => {
console.log('最终请求结果', res)
}).catch((err)=>{
console.log(err,'--')
})
from all-of-frontend.
function request(type,time){
return new Promise((r,j)=>{
setTimeout(()=>{
if(Math.random()>0.5){
r(type)
}else{
r(request(type,time))
console.log('请求失败',type)
}
},parseInt(time))
})
}
const A=request('A',Math.random()*1000);
const B=request('B',Math.random()*1000);
const C=request('C',Math.random()*1000);
const D=request('D',Math.random()*1000);
Promise.all([A,B,C,D]).then(res=>{
console.log('全部请求成功',res)
})
from all-of-frontend.
let errorRequestType = [];
const http = (type) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(type);
Math.ceil(Math.random() * 100) % 2 ? resolve() : reject();
}, Math.ceil(Math.random() * 1000))
}).catch(() => errorRequestType.push(type))
}
const requestAll = (requests) => {
Promise.all(requests).then(() => {
console.log('errorRequest.length:', errorRequestType.length);
if (errorRequestType.length) {
requestAll(errorRequestType.map(t => http(t)));
errorRequestType = [];
}
});
}
requestAll([http('A'), http('B'), http('C'), http('D')])
from all-of-frontend.
function request(data) {
return new Promise((resolve, reject) => {
const faile = Math.random() > 0.5 ? true : false; // 模拟失败
setTimeout(() => {
// console.log('faile----', faile);
if (faile) {
reject();
} else {
resolve({
success: true,
detail : data,
});
}
}, 1000);
}).catch(() => {
return {
success: false,
detail: data,
}
});
};
const detail = ['A', 'B', 'C', 'D'];
let list = [];
function handle(arr) {
list = [];
arr.forEach((item) => {
list.push(request(item));
});
// console.log(list);
Promise.all(list).then((data) => {
let temp = [];
// console.log(data);
data.forEach((item) => {
if (!item.success) {
console.log(`${item.detail}请求失败,准备重新请求`);
temp.push(item.detail);
} else {
console.log(`${item.detail}请求成功`);
}
})
if (temp.length != 0) {
// console.log('enter');
handle(temp);
}
})
}
handle(detail);
![Uploading image.png…]()
A请求失败,准备重新请求
B请求成功
C请求成功
D请求失败,准备重新请求
A请求成功
D请求失败,准备重新请求
D请求成功
from all-of-frontend.
function request(data) {
return new Promise((resolve, reject) => {
const faile = Math.random() > 0.5 ? true : false; // 模拟失败
setTimeout(() => {
// console.log('faile----', faile);
if (faile) {
reject();
} else {
resolve({
success: true,
detail : data,
});
}
}, 1000);
}).catch(() => {
return {
success: false,
detail: data,
}
});
};
const detail = ['A', 'B', 'C', 'D'];
let list = [];
function handle(arr) {
list = [];
arr.forEach((item) => {
list.push(request(item));
});
// console.log(list);
Promise.all(list).then((data) => {
let temp = [];
// console.log(data);
data.forEach((item) => {
if (!item.success) {
console.log(`${item.detail}请求失败,准备重新请求`);
temp.push(item.detail);
} else {
console.log(`${item.detail}请求成功`);
}
})
if (temp.length != 0) {
// console.log('enter');
handle(temp);
}
})
}
handle(detail);
![Uploading image.png…]()
from all-of-frontend.
const httpRequest = (type, time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() * 1000 > time) {
console.log(`请求${type}成功`);
resolve;
} else {
console.log(`重新请求${type}`);
reject({ type: type, time: time });
}
}, time);
}).catch((err) => {
httpRequest(err.type, err.time);
});
};
const A = httpRequest("A", Math.random() * 1000);
const B = httpRequest("B", Math.random() * 1000);
const C = httpRequest("C", Math.random() * 1000);
const D = httpRequest("D", Math.random() * 1000);
Promise.all([A, B, C, D]).then((res) => {
console.log(res);
});
from all-of-frontend.
// 异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试。
// Promise.all([A, B, C, D])
// 4 个请求完成后发现 AD 请求失败了,如果让 AD 请求重试
const fetchData = (url) => {
let time = Math.random() * 1000;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() * 1000 > time) {
console.log(`${url}请求成功`);
resolve;
} else {
console.log(`${url}请求失败,重新请求`);
reject({ url: url });
}
}, time);
}).catch((err) => {
fetchData(err.url);
});
};
const fetchList = [fetchData("A"), fetchData("B"), fetchData("C"), fetchData("D")]
Promise.all(fetchList).then((res) => {
console.log(res);
});
from all-of-frontend.
let num = 0;
function pall(fn){
return new Promise((resolve,reject)=>{
fn(resolve,reject)
}).then((result)=>{
console.log(result)
return Promise.resolve(result)
}).catch((e)=>{
console.log(e)
return pall(fn)
})
}
// 第一个promise
const p1 = pall((resolve,reject)=>{
setTimeout(()=>{
resolve("这是p1的输入结果")
},1000)
})
// 第二个promise
const p2 = pall((resolve,reject)=>{
num += 1;
if(num > 4){
setTimeout(()=>{
resolve("这是p2的输入结果")
},1000)
}else{
// 模拟失败请求
setTimeout(()=>{
reject('这是请求出错的第' + num + '次')
},1000)
}
})
// 第三个promise
const p3 = pall((resolve,reject)=>{
setTimeout(()=>{
resolve("这是p3的输入结果")
},1000)
})
Promise.all([p1,p2,p3]).then((r)=>{
console.log(r)
}).catch((e)=>{
console.log('还是出错',e)
})
from all-of-frontend.
/**
* 题目 异步请求通过 Promise.all 处理,怎么让其中失败的所有请求重试
* 本题的核心**就是在 promise.catch 中捕获错误!
*/
const http = function(data){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(Math.random() <0.5){
console.log(`${data} 第一次就请求成功啦~`);
resolve(data);
}else{
reject(data);
console.log(`${data} 第一次请求失败啦!!!!`)
}
},Math.random() * 1000)
}).catch((rej)=>{
http(rej);
})
}
Promise.all([http('A'),http('B'),http('C'),http('D')]).then((res)=>{
console.log('请求成功')
})
from all-of-frontend.
代码:
const requestA = function (reTry = true) {
return new Promise((resolve, reject) => {
throw Error("A");
}).catch((err) => {
if (reTry) {
console.log("请求A失败重试");
requestA(false);
}
});
};
const requestB = function (reTry = true) {
return new Promise((resolve, reject) => {
console.log("bbbb");
resolve("B");
}).catch((err) => {
if (reTry) {
console.log("请求B失败重试");
requestB(false);
}
});
};
const requestC = function (reTry = true) {
return new Promise((resolve, reject) => {
console.log("cccc");
resolve("C");
}).catch((err) => {
if (reTry) {
console.log("请求C失败重试");
requestC(false);
}
});
};
const requestD = function (reTry = true) {
return new Promise((resolve, reject) => {
throw Error("D");
}).catch((err) => {
if (reTry) {
console.log("请求D失败重试");
requestD(false);
}
});
};
Promise.all([requestA(), requestB(), requestC(), requestD()])
.then(
(res) => {
console.log(res, "res----");
},
(err) => {
console.log(err, "err----");
}
)
.catch((err) => {
console.log(err, "catch----");
});
运行结果:
bbbb
cccc
请求A失败重试
请求D失败重试
(4) [undefined, "B", "C", undefined] "res----"
from all-of-frontend.
from all-of-frontend.
思路:在catch里重试
function mockAsyncFn(arg) {
return () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
console.log(`success get ${arg}`);
resolve(arg);
} else {
console.log(`request ${arg} err`);
reject(arg);
}
}, Math.random() * 2000);
});
};
}
function retry(fn, maxRetry = 3) {
return fn().catch((err) => {
// console.log("maxRetry", maxRetry);
if (--maxRetry > 0) {
console.log(`request failed err ${maxRetry}`);
return retry(fn, maxRetry);
} else {
return Promise.reject(e);
}
});
}
const result = ["A", "B", "C", "D"].map((item) => retry(mockAsyncFn(item)));
Promise.all(result)
.then((res) => {
console.log("res", res);
})
.catch((e) => {
console.log("rej", e);
});
from all-of-frontend.
// 基于 Promise 封装一个可指定重试次数的异步请求方法
async function request(name, retryNum = 1) {
let result;
for (let i = 0; i <= retryNum; i++) {
try {
// 是否进入重试
const isRetry = i > 0;
if (isRetry) {
console.log(`重试${name}请求:第${i}次`);
}
// 这里是模拟异步请求
result = await new Promise((resolve, reject) => {
const random = Math.random();
setTimeout(() => {
if (random < 0.2) {
reject(`${name}请求出错`);
} else {
if (isRetry) {
console.log(`${name}请求重试${i}次后成功`);
}
resolve(name);
}
}, random * 2000);
});
// 如果请求成功,则跳出循环
break;
} catch(e) {
// 最终将错误再抛出
if (retryNum === i) {
result = Promise.reject(e);
}
}
}
return result;
}
const p = Promise.all([request('A'), request('B'), request('C'), request('D')]);
p.then(result => console.log(result)).catch(e => console.log(e));
from all-of-frontend.
function httpRequest(value, retry){
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(value);
console.log(value, retry ? '重新请求成功' : '第一次请求成功');
} else {
reject();
console.log(value, retry ? '重新请求失败' : '第一次请求失败');
}
}, Math.random() * 1000);
}).catch(() => {
return httpRequest(value, true);
});
}
const queue = [
httpRequest('A'),
httpRequest('B'),
httpRequest('C'),
httpRequest('D')
];
Promise.all(queue)
.then(res => {
console.log('成功',res)
}).catch(err => {
console.log('失败', err);
})
from all-of-frontend.
Related Issues (20)
- Potential security issue
- Add social banner. HOT 1
- 项目地址挂了
- 顺序有问题
- 第十九题:JS 中的数据存放位置 HOT 21
- 第二十题:实现深拷贝函数 HOT 17
- 第二十一题:Vue 有了数据劫持为什么还要 DOM diff? HOT 11
- 第二十二题:0.1 + 0.2 !== 0.3? HOT 20
- 第二十三题:普通函数和箭头函数的区别是什么? HOT 30
- 第二十四题:Babel 会将箭头函数编译成什么? HOT 19
- 第二十五题:三问闭包 HOT 22
- 第二十六题:如何实现 sleep 函数 HOT 25
- 第二十七题:开发中有遇到过比较难定位的问题吗? HOT 12
- 第二十八题:以下代码输出什么?为什么? HOT 17
- 第二十九题:以下代码输出什么? HOT 7
- 关于为什么出现域名以及为什么域名和ip并用的场景
- 第三十一题:将48位的时间位图格式化成字符串
- 插眼 HOT 1
- 如何自学的图片为空白内容 HOT 2
- 画图工具的使用问题 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from all-of-frontend.