current position:Home>Five common scenarios and solutions with too deep nesting at the front end

Five common scenarios and solutions with too deep nesting at the front end

2021-08-27 08:59:02 Front end GOGO

Code nested too deeply is not readable , Poor maintainability . Make people produce “ Awe ”. such as :

fetchData1(data1 =>
  fetchData2(data2 =>
    fetchData3(data3 =>
      fetchData4(data4 =>
        fetchData5(data5 =>
          fetchData6(data6 =>
            fetchData7(data7 =>
              done(data1, data2, data3, dat4, data5, data6, data7)
            )
          )
        )
      )
    )
  )
)
 Copy code 

big-head.gif

In this paper, 5 Scenarios and solutions that are too deeply nested .

scene 1: Back to hell

Use callback function to handle multiple serial asynchronous operations , It will cause deep nesting . Be commonly called “ Back to hell ”. Such as :

fetchData1(data1 =>
  fetchData2(data2 =>
    fetchData3(data3 =>
      done(data1, data2, data3)
    )
  )
)
 Copy code 

Solution

programme 1: Promise

use Promise Serial can be asynchronous , Handle as a chained call . use Promise Rewrite the above code as follows :

let data1, data2, data3
fetchData1()
  .then(data => {
    data1 = data
    return fetchData2()
  })
  .then(data => {
    data2 = data
    return fetchData3()
  })
  .then(data => {
    data3 = data
    done(data1, data2, data3)
  })
 Copy code 

I feel much better after changing my mood ~

nice.gif

Be careful : above fetchData1,fetchData2,fetchData3 The return values of must all be Promise object . similar :

function fetchData1 () {
  return new Promise(resolve) {
    ...
    //  I'm back 
    resolve(data)
  }
}
 Copy code 

If these asynchronies can operate in parallel , It can be written like this :

Promise.all([
  fetchData1(),
  fetchData2(),
  fetchData3()
]).then(([data1, data2, data3]) => {
  done(data1, data2, data3)
})
 Copy code 

programme 2: async/await

async/await Than using Promise More elegant . use async/await Rewrite the above code as follows :

async function fetch() {
  const data1 = await fetchData1()
  const data2 = await fetchData2()
  const data3 = await fetchData3()
  done(data1, data2, data3)
}
 Copy code 

Be careful : above fetchData1,fetchData2,fetchData3 The return values of must also be Promise object . meanwhile , use await Function of , Must precede the function name with async.

scene 2: if nesting

In a conditional statement , If there are many judgment conditions , There will be The nesting is very deep Or judge the situation with long conditions . such as , Judge whether a value is : 1 To 100 Between , Can be 3 and 5 Even number of integral division . That's how it's written :

const isEvenNum = num => Number.isInteger(num) && num % 2 === 0
const isBetween = num => num > 1 && num < 100
const isDivisible = num => num % 3 === 0 && num % 5 ===  0

if (isEvenNum(num)) { //  It's even 
  if(isBetween(num)) { // 1  To  100  Between 
    if(isDivisible(num)) { //  Can be  3  and  5  to be divisible by 
        return true
    }
    return false
  }
  return false
}
return false
 Copy code 

Solution

programme 1: Put the judgment condition results in the array

Put the judgment condition results in the array , Nested conditions can be judged , Change to the judgment of traversing the array value . The code implementation is as follows :

return [isEvenNum(num), isBetween(num), isDivisible(num)]
  .every(flag => flag)
 Copy code 

programme 2: Use a third-party library Akua

Akua You can convert conditional nesting into chained calls . The code implementation is as follows :

const flag = false
new akua()
  .inject(isEvenNum(num), 'isEvenNum', () => {
    console.log(' It's even ')
  })
  .inject(isBetween(num), 'isEvenNum->isBetween', () => {
    console.log('1  To  100  Between ')
  })
  .inject(isDivisible(num), 'isBetween->isDivisible', () => {
    console.log(' Can be  3  and  5  to be divisible by ')
    flag = true
  })
  .parse()

return flag
 Copy code 

scene 3: Function call nesting

Execute multiple function calls , The output of each function is the input of the next function , Will cause deep nesting . Such as :

toTable( //  Step four :  On the table 
  fry( //  The third step :  Scrambled eggs 
    handle( //  The second step :  Beating eggs 
      buy(20) //  First step :  Buy eggs 
    )
  )
)
 Copy code 

The above code simulates the process of frying eggs : Buy eggs -> Beating eggs -> Scrambled eggs -> On the table .

Solution

programme 1: Write in multiple steps

Write in multiple steps , Receive the call result of the last function with a temporary variable . The implementation code is as follows :

let egg = buy(20)
egg = handle(egg)
egg = fry(egg)
egg = toTable(egg)
console.log(egg)
 Copy code 

programme 2: Encapsulate as a function

Recursively , Put the execution result of the previous function , Pass to the next function . The code is as follows :

pipe(20, [
  buy,
  handle,
  fry,
  toTable
]);

function pipe(prev, fnArr) {
  if(fnArr.length > 0) {
    const res = fnArr.shift()(prev)
    return pipe(res, fnArr)
  }  
  return prev
}
 Copy code 

scene 4: React High order component nesting

stay React Written applications , There will be a component that is used by many High order component (HOC) The parcel , Cause deep nesting . Such as :

class Comp extends React.Component {...}

Wrapper5(
  Wrapper4(
    Wrapper3(
      Wrapper2(
        Wrapper1(Comp)
      )
    )
  )
)

 Copy code 

Solution

programme 1: Use class decorators

It is written as follows :

@Wrapper5
@Wrapper4
@Wrapper3
@Wrapper2
@Wrapper1
class Comp extends React.Component {...}
 Copy code 

Be careful : Some dependencies need to be installed in the project to use the decorator . If it is Webpack project , To install @babel/plugin-proposal-decorators. Specific view : stay React Use custom decorators in projects .

programme 2: Change high-level components to custom components Hook

Used in components Customize Hook It's a flat structure , No nesting . Change a class component into a function component , Change high-level components to custom components Hook Can solve the problem of nesting . It is written as follows :

function Comp () {
  const tool1 = useWrapper1(...)
  const tool2 = useWrapper2(...)
  const tool3 = useWrapper3(...)
  const tool4 = useWrapper4(...)
  const tool5 = useWrapper5(...)
}
 Copy code 

This scheme makes great changes to the original code , Just for your reference .

scene 5: React Context nesting

stay React Written applications , It can be used Context To manage data sharing between subcomponents . If you share a lot of data , And different types , Easy to cause damage to the top assembly Context The nesting is very deep . Such as :

<PageContext.Provider
  value={...}
>
  <User.Provider value={...} > <Project.Provider value={...} > <ChildComp /> </Project.Provider> </User.Provider>
</PageContext.Provider>
 Copy code 

Solution

The above nesting can be solved by writing in multiple steps . Implementation code :

let content = <ChildComp />

content = (
  <Project.Provider value={...} > {content} </Project.Provider>
)

content = (
  <User.Provider value={...} > {content} </User.Provider>
)

content = (
  <PageContext.Provider value={...} > {content} </PageContext.Provider>
)
 Copy code 

summary

Nesting leads to poor readability and maintainability of the code . To solve the nesting problem , It's essentially transforming nested code into flat code .

copyright notice
author[Front end GOGO],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827085857071x.html

Random recommended