This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August

asynchronous

Because javaScript is single-threaded, there are a lot of asynchronous operations in the program, such as when we fetch data using Ajax, such as callback functions.

Suppose I have a requirement in the project I’m working on right now:

  • A request to get the table data is invoked first
  • Get the details of one of the data based on the data returned by this request

We’ve all written about this, but I’m going to use axios, the Ajax library

axios.get('/api/table_list')
    .then(res= >{
            let id = res[0].tableId
            axios.get('/api/table_detail? id='+id)
                    .then(res= >{
                            randerToView(res)
                    })
                    .catch(err= >handelErr(err))
    })
    .catch(err= >handelErr(err))

function randerToView(object){}
function handelErr(err){}
Copy the code

Such code is eye-readable, and the logic of the code has to be followed, so it’s not friendly, or callback hell for short.

Fortunately, there is the Promise API.

promise

ECMAscript 6 provides an API such as Promise. It represents events that will happen in the future and is therefore used to pass the result of an asynchronous operation.

The biggest benefit of this API, I think, is that it avoids the above callback hell of writing. Because of Promise’s three states, it allows it to express its nested layers of callback functions synchronously.

function getTableList(){
    return new Promise((resolve, reject) = >{
        axios.get('/api/table_list').then(_= >{
            resolve(_[0].tableId)
        })
    })
}

function getTableDetailById(id){
    axios.get('/api/table_detail? id='+id).then(_= >{
        randerToView(_)
    })
}

getTableList.then(getTableDetailById)
Copy the code

This is a bit more code than using asynchronous callbacks directly, but it’s clear that the logic of the code is more in line with our daily thinking habits.

And often in programs, it’s not that less code is better.

Because less code requires more thought, not only a waste of brain cells, but after a while, without comments, you are likely to have forgotten all the thought at the time, resulting in maintenance difficulties.

Async and await

Async and await can greatly improve code readability and reduce code volume to staggering levels. This is thanks to the advent of ECMAscript 7.

For example, use async and await as required above:

(asycn ()=>{
    let res = await axios.get('/api/table_list')
    let id = res[0].tableId
    let detail = await axios.get('/api/table_detail? id='+id)
    randerToView(detail)
})()
Copy the code

So many people like to use async and await a lot in programming

The problem with this is that we cannot catch an asynchronous error when it occurs, so the code should be placed in a try{}catch(){} statement

try{
    let res = await axios.get('/api/table_list')
    let id = res[0].tableId
    let detail = await axios.get('/api/table_detail? id='+id)
    randerToView(detail)
}catch(err){
    handelErr(err)
}
Copy the code

This code looks ok, but it’s too much. If you think about it, this try… catch… It doesn’t feel very elegant either. Can’t there be a solution to the programmer’s obsession with cleanliness?

Analysis of the

If we print axios.get(‘/ API /table_list’), we see that it is a Promise, and await only gets resolve, so reject is useless.

try… catch… The statement catches any errors within its code block, and thus can catch a reject state.

So maybe we can try to implement a method ourselves

If we first catch a Promise’s Error and then put both the Error and the normal data into another Promise’s resolve and pass to await, The latter Promise’s await has both normal data and Error states.

implementation

export handlerPromise = (promise) = > promise.then(data= > [null, data]).catch(err= > [err])
Copy the code

validation

In the program, deletion is handled very carefully, and usually a confirmation box pops up to prompt the user whether or not to delete data.

The Message module in elementUI provides a complete implementation.

Each page may have data that needs to be deleted by the user, so we can extract a confirmation box as a common method.

// val is the data to be deleted. Type is Array
export const delDialog = val= >
  new Promise((resolve, reject) = > {
    if(! val.length) { Message.info('Please select data to delete')
      reject(new Error()}else {
      MessageBox.confirm('Will delete the selected data, are you sure? '.'tip', {
        cancelButtonText: 'cancel'.confirmButtonText: 'sure'.type: 'warning'
      }).then(() = > {
        resolve(val)
      }).catch((action) = > {
        reject(action)
      })
    }
  })
Copy the code

Just introduce it on the page you want to use.

import { delDialog , handlerPromise } from '@/utils/del'.methods: {handleRemove(){
            let [dialogErr, res] = await handlerPromise(delDialog (this.multipleSelection))
            if(dialogErr) return

            let res = await tableDelete(res)
            // Since ajax errors are already caught and alerted to the user at the top level, just return here
            if(! res)return

            this.getTableList()
    }
}
Copy the code

Seems to be a lot of convenience, if it helps you, please give me a thumbs-up