iT邦幫忙

1

在 map 裡面檢查每個 key ,有錯誤如何跳出?

let thisValid = ``
let vo = this.inputList.map((key, idx) => {
                let container = {}
                container.defineMap = this.handleItem(key.defineMap)
                thisValid = this.handleVoValid(key, container, idx);
                if (!thisValid) 
                    return
                container.groupName = key.groupName
                container.isGourpRequire = key.isGourpRequire
                return container
            })

handleVoValid 會檢查 container.defineMap 裡面的 key 跟 value 有無符合條件
若錯誤則回傳 false
但我查了一下發現 map 跟 foreach 都是會做完
沒辦法中途跳出
這導致假設三個 obj 裡面 1 跟 2 即使 false,第三個若成功,thisValid 也會為 true 的問題
請問要怎麼強制跳出 map 不繼續往下執行?

3
通靈亡
iT邦研究生 5 級 ‧ 2020-06-10 12:14:31
最佳解答

thisValid 在這個情境不適合用foreach跟map
比較適合用every
假定你的 thisValid 存的是 true 或 false,可以這樣改

let thisValid = this.inputList.every((key, idx) => {
    let container = {}
    container.defineMap = this.handleItem(key.defineMap)
    return this.handleVoValid(key, container, idx);
})

若假定vo存的是所有有效的值,可以用簡單的&&邏輯運算處理
一開始thisValid假設是true
只要後面有值是false,thisValid && currentIsValid 皆為false

let thisValid = true
let vo = this.inputList.map((key, idx) => {
    let currentIsValid = true
    let container = {}
    container.defineMap = this.handleItem(key.defineMap)
    
    // 檢查是否有效
    currentIsValid = this.handleVoValid(key, container, idx);
    thisValid = thisValid && currentIsValid
    
    // 目前的資料無效,回傳空JSON
    if (!currentIsValid) 
       return {}
    
    // 目前的資料有效,回傳指定的JSON
    container.groupName = key.groupName
    container.isGourpRequire = key.isGourpRequire
    return container
  })

又或者如果你不希望vo只存有效的json,不要有空json
foreach可以這樣改寫

let vo = []
let thisValid = true
this.inputList.foreach((key, idx) => {
    let currentIsValid = true
    let container = {}
    container.defineMap = this.handleItem(key.defineMap)
    
    // 檢查是否有效
    currentIsValid = this.handleVoValid(key, container, idx);
    thisValid = thisValid && currentIsValid
    
    // 目前的資料有效,新增目前資料的json到array裡面
    if (currentIsValid === true) {
       container.groupName = key.groupName
       container.isGourpRequire = key.isGourpRequire
       vo.push(container)
    }
  })

如果硬要在loop function 實作break的話

let CustomBreakException = {}

let vo = []
let thisValid = true
try {
    this.inputList.forEach((key, idx) =>  {
        let container = {}
        container.defineMap = this.handleItem(key.defineMap)
        
        // 檢查是否有效
        thisValid = this.handleVoValid(key, container, idx);

        // 目前的資料無效,回傳空陣列,拋出自訂例外
        if (!thisValid) {
            vo = []
            throw CustomBreakException
        }
        
        container.groupName = key.groupName
        container.isGourpRequire = key.isGourpRequire
        vo.push(container)

    });
} 
catch (e) {
    if (e !== CustomBreakException) 
        throw e
}
froce iT邦大師 1 級 ‧ 2020-06-10 15:07:30 檢舉

對啊,明明就有every,先檢查是不是全部都符合就好。

後來看了一下 mdn 先用 every 去檢查真的比較適合
some 好像不是我那樣用的 XD

通靈亡 iT邦研究生 5 級 ‧ 2020-06-10 16:35:10 檢舉

listennn08
或者像你上面說的,用一般的for迴圈處理反而最直接單純。
硬用 loop function 配 try catch 實作break 根本脫褲子放屁 XD

2
listennn08
iT邦高手 9 級 ‧ 2020-06-10 11:59:31

用 some 吧

const valid = 3;
const arr = [1, 2, 3];
let validarr =[];
arr.some(el => {
	if (el != valid)
		validarr.push(el);
})
console.log(validarr); // [1, 2]
看更多先前的回應...收起先前的回應...
松松 iT邦研究生 2 級 ‧ 2020-06-10 12:13:32 檢舉

我個問題
我的目的是當 thisValid 回來是 false 時,我不想讓 map 繼續執行,此時我會出現錯誤提示框
直到 container.defineMap 完全符合我的格式
才會 return vo
比較不像是篩選的行為

那用 for 或 while 會比較好吧

let valid = true;
let arr = [true, false, true];
let validarr =[]

for (let i=0; i< arr.length; i++) {
	if (arr[i]) {
		validarr.push(arr[i]);
	} else {
		break;
	}
}
console.log(validarr)
if (validarr.filter(el=> el==true).length == validarr.length)
    return validarr
通靈亡 iT邦研究生 5 級 ‧ 2020-06-10 12:52:29 檢舉

如果硬要在loop function 實作break,要用拋出例外的作法
詳細的例子放在我下面的回答

大致長這樣:

var CustomBreakException = {}

try {
    this.inputList.forEach(function(v) {
        // 目前的資料無效,回傳空陣列,拋出自訂例外
        if (!currentIsValid) {
            vo = []
            throw CustomBreakException
        }
        
        container.groupName = key.groupName
        container.isGourpRequire = key.isGourpRequire
        vo.push(container)
    });
} 
catch (e) {
    if (e !== CustomBreakException) 
        throw e
}

如果一定要用 loop function 可以寫 try catch 啦
不想寫 try catch 就用 for 就好了

2
w4560000
iT邦新手 4 級 ‧ 2020-06-10 12:21:51
let inputList = ["000","123"];

let vo = inputList.map(x => {
                if (x === "123") 
                throw Error("error");
                return x
            })

我要發表回答

立即登入回答