Promise.all回调未触发:Promise内嵌套forEach循环的异常问题
问题原因
- 空数组的
forEach不会执行回调函数,你的代码里data.ocupacao_baixa.count、data.ocupacao_moderada.count都是空数组,对应的Promise里的resolve逻辑写在forEach回调内部,永远不会被执行,这两个Promise会一直处于pending状态,导致Promise.all的回调永远不会触发。 - 你初始化
horas数组时使用的new Array(24).fill([0, 0, 0, 0])语法,会给24个位置填充同一个数组的引用,修改任意一个位置的元素都会同步修改所有位置的数值,属于隐藏逻辑漏洞。
修复方案
首先修改Promise的逻辑:把resolve逻辑移到forEach外面,不管数组是否为空,处理完所有元素后直接resolve。其次修改horas数组的初始化方式,保证每个子数组都是独立引用。
另外你的所有操作都是同步逻辑,实际不需要用Promise.all包装,直接按顺序执行三次forEach也能拿到正确结果,使用Promise属于多余操作。
修复后代码如下:
// original code: const data = res.data.data; const data_ = { success: true, data: { ocupacao_baixa: { count: [], rows: [] }, ocupacao_moderada: { count: [], rows: [] }, ocupacao_elevada: { count: [{ date_part: 13, count: "1" }], rows: [{ date_part: 13 }], }, }, }; const data = data_.data; // 修复1:初始化独立子数组 let horas = Array.from({length: 24}, () => [0, 0, 0, 0]); console.log("DEBUG:horas0", horas); let getOcupacaoBaixa = new Promise((resolve, reject) => { data.ocupacao_baixa.count.forEach((element) => { console.log("DEBUG:element", element); console.log("DEBUG:horas1", horas); console.log( "DEBUG:horas[" + element.date_part + "]", horas[element.date_part] ); horas[parseInt(element.date_part)][1] = parseInt(element.count); }); // 修复2:forEach结束后直接resolve,不需要判断索引,空数组也会执行 resolve(); }); let getOcupacaoModerada = new Promise((resolve, reject) => { data.ocupacao_moderada.count.forEach((element) => { console.log("DEBUG:element", element); console.log("DEBUG:hora2s", horas); console.log( "DEBUG:horas[" + element.date_part + "]", horas[element.date_part] ); horas[parseInt(element.date_part)][2] = parseInt(element.count); }); resolve(); }); let getOcupacaoElevada = new Promise((resolve, reject) => { data.ocupacao_elevada.count.forEach((element) => { console.log("DEBUG:element", element); console.log("DEBUG:horas3 ", horas); console.log( "DEBUG:horas[" + element.date_part + "]", horas[element.date_part] ); horas[parseInt(element.date_part)][3] = parseInt(element.count); }); resolve(); }); Promise.all([getOcupacaoBaixa, getOcupacaoModerada, getOcupacaoElevada]).then( () => { console.log("DEBUG:dadosMostrar"); let dadosMostrar = [...horas]; dadosMostrar.forEach((a, i, arr) => { let b = [...arr[i]]; b.shift(); arr[i] = [i.toString(), ...b]; }); this.setState({ dadosMostrar: dadosMostrar }); } );
内容的提问来源于stack exchange,提问作者Tiago
相关产品推荐
相关产品推荐

