GithubHelp home page GithubHelp logo

Comments (42)

1742284240 avatar 1742284240 commented on May 13, 2024 16
  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)
  })

Edit promiss.all错误处理

image

from all-of-frontend.

yancongwen avatar yancongwen commented on May 13, 2024 4

请求失败自动重传机制

使用 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)
})

image

from all-of-frontend.

pengpeng9413 avatar pengpeng9413 commented on May 13, 2024 2

感觉这道题没啥意思

from all-of-frontend.

BillScott1024 avatar BillScott1024 commented on May 13, 2024 1

输出:
image

源码:

/**
 * 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();

在线运行:
Edit priceless-curran-hc8e1

from all-of-frontend.

secret344 avatar secret344 commented on May 13, 2024
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.

goldEli avatar goldEli commented on May 13, 2024
// 模拟第一次请求失败
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.

XianHuiDeDiZhongHai avatar XianHuiDeDiZhongHai commented on May 13, 2024
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.

cduyzh avatar cduyzh commented on May 13, 2024

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.

learnRy avatar learnRy commented on May 13, 2024
//经过一层包装把失败请求的返回回去
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.

panalanjun avatar panalanjun commented on May 13, 2024

待完善的优化

对于失败的请求,目前使用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.

huangpingcode avatar huangpingcode commented on May 13, 2024
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.

vandvassily avatar vandvassily commented on May 13, 2024
// 异步请求通过 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.

Ecaknight avatar Ecaknight commented on May 13, 2024
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.

free-qiaochen avatar free-qiaochen commented on May 13, 2024
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.

adam-zhou avatar adam-zhou commented on May 13, 2024
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.

l0ng09 avatar l0ng09 commented on May 13, 2024
/**
 * 异步请求通过 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.

abu-ab avatar abu-ab commented on May 13, 2024
 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);
     });

image

from all-of-frontend.

SunshineZJJ avatar SunshineZJJ commented on May 13, 2024
  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.

yang-1234 avatar yang-1234 commented on May 13, 2024
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.

teefing avatar teefing commented on May 13, 2024
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.

GeekNoble avatar GeekNoble commented on May 13, 2024

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.

AbigaiL533 avatar AbigaiL533 commented on May 13, 2024
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.

mengzhe510 avatar mengzhe510 commented on May 13, 2024

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.

chen870370470 avatar chen870370470 commented on May 13, 2024

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.

a11995910 avatar a11995910 commented on May 13, 2024
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.

kevinxft avatar kevinxft commented on May 13, 2024
// 参考了上面大兄弟的代码
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.

yangdong9527 avatar yangdong9527 commented on May 13, 2024
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.

ErnestWangZuNian avatar ErnestWangZuNian commented on May 13, 2024
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.

liuqiuzhen avatar liuqiuzhen commented on May 13, 2024

参考了网上的答案 并测试了其它几种情况
// 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.

lucas270 avatar lucas270 commented on May 13, 2024

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.

weiChow avatar weiChow commented on May 13, 2024
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.

ByeLe avatar ByeLe commented on May 13, 2024
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.

ByeLe avatar ByeLe commented on May 13, 2024
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.

docterlei avatar docterlei commented on May 13, 2024
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.

monadaa avatar monadaa commented on May 13, 2024
// 异步请求通过 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.

owlsignl avatar owlsignl commented on May 13, 2024
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.

ahaghosthao avatar ahaghosthao commented on May 13, 2024
/**
 * 题目 异步请求通过 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.

muzishuiji avatar muzishuiji commented on May 13, 2024
代码: 
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.

mingyuesun avatar mingyuesun commented on May 13, 2024

image

from all-of-frontend.

liuestc avatar liuestc commented on May 13, 2024

思路:在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.

xiaocongWang avatar xiaocongWang commented on May 13, 2024
// 基于 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.

wenhuiyang-luck avatar wenhuiyang-luck commented on May 13, 2024
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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.