Skip to content

await

  1. await后面的Promise对象,运行结果可能是rejected,那么会报错
    1. 报错了后面就不会执行了
    2. 所以最好把await命令放在try...catch代码块中。
javascript

async function fn(){
    await Promise.reject('出错了') // await出错了,下面就不会执行了
    await Promise.resolve('hello')
}

fn().then(res => {
    console.log(res)
})

try {
    // 把可能出错的代码,放在这里
    const box = document.querySelector('.div')
    box.innerHTML = 'wahh'
    console.log(box)
} catch(err) {
    // 一旦try中的代码,出错了,报错了,都会捕获到这里,并且控制台不会打印错误
    console.log(err)
}
// console.log(123123)/


// ==>  应用 try-catch 
async function fn(){
    try {
        await Promise.reject('出错了') // await出错了,下面就不会执行了
    } catch(err) {
        console.log(err)
    }
    // async 函数, 里面如果没有return,fn()执行完,结果是成功态的undefined
    
    return await Promise.resolve('hello')
    // return 'hello'
    // return 666
}

fn().then(res => {console.log(res)})

await-promise.all

继发:一件事情发生后,继而发生另一件事 并发:同一时间执行多个任务

javascript
// 继发:一件事情发生后,继而发生另一件事  同步  串联
// 并发:同一时间执行多个任务            异步  并联

// 4. 多个await关键字后面的异步操作,如果不存在继发关系,最好让他们同时执行

const api_news = 'http://ajax-api.itheima.net/api/news'
const api_books = 'http://ajax-api.itheima.net/api/books'
const api_robot = 'http://ajax-api.itheima.net/api/robot?spoken=你好'

async function sendRequest(url){
   return await fetch(url).then(res => res.json())
    // console.log(fetch(url).then(res => res.json()))
    // 1. fetch(url).then() 返回的是什么? promsie对象
    // 2. let res = await fetch().then()  ==> res是promise对象的结果
    // 3. sendRequest() 它调用完,返回的 也是 promsie对象
}


// 继发:下一个请求的参数,如果是上一个接口返回值里面取
;(async () => {
    // await 会阻塞后面代码的执行 
    let books = await sendRequest(api_books)
    console.log(books)
    let news = await sendRequest(api_news)
    console.log(news)
    let robot = await sendRequest(api_robot)
    console.log(robot)
  // 这样写,比较耗时,上一个接口返回值了,才能继续下一个请求的发送
})()

// 并发 三个请求没有关联
;(async () => {
    let [books, news, robot] = await Promise.all([sendRequest(api_books),sendRequest(api_news),sendRequest(api_robot)])
    console.log(books, news, robot)
})()

promise链式编程 => async / await

javascript
// 链式编程
// 需求:延时2s秒输出红色,然后再延时1s输出黄色,然后再延时3s输出绿色
// 回调函数的嵌套 ==> 回调地狱 , promise解决 => 终极方案 async/await

// const sleep = (msg, ms) => {
//     return new Promise((resolve) => {
//         setTimeout(() => {
//             resolve(msg)
//         }, ms)
//     })
// }
// sleep('啊哈', 1000) 这个表达式的值是什么 ? 或者说它返回什么?

const sleep = (msg, ms) => new Promise(resolve => setTimeout(() => {resolve(msg)}, ms))

sleep('红色', 2000).then(res => {
    // 1. .then() 中 ,不写return, 相当于then中没有返回值,返回一个成功态的promise,结果是undefined
    // 2. 写了return 并且return的是一个promise对象,就要等这个promise对象状态的的结果,才能进入下一个then的回调中
    console.log(res)
    // resolve()
    return sleep('黄色', 1000)
}).then(res => {
    console.log(res)
    // resolve()
    return sleep('绿色', 3000)
}).then(res => {
    console.log(res)
})

// async function fn(){
//     let res1 = await sleep('红色', 2000)
//     console.log(res1)
//     let res2 = await sleep('黄色', 1000)
//     console.log(res2)
//     let res3 = await sleep('绿色', 3000)
//     console.log(res3)
// }
// fn()

;(async () => {
    let res1 = await sleep('红色', 2000)
    console.log(res1)
    let res2 = await sleep('黄色', 1000)
    console.log(res2)
    let res3 = await sleep('绿色', 3000)
    console.log(res3)
})()

async不会阻塞function外部的执行

javascript
const sleep = (s) => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(s)
        }, s * 1000)
    })
}

async function func1() {
    const res1 = await sleep(1) 
    console.log('res1:', res1)
    const res2 = await sleep(3) 
    console.log('res2:', res2)

}

async function func2() {
    // await func1()
    const res3 = await sleep(2) 
    console.log('res3:', res3)
    const res4 = await sleep(4) 
    console.log('res4:', res4)
}

// await 阻塞的是async function里面的代码,不会阻塞外面的函数的执行 
// console.log('top')
func1() // func1 是用async修饰了,是promise,内部又有await,异步的
func2()
// console.log('bottom')

// Q: 我想 func1 执行完,再执行func2? 

// async function func3(){
//     await func1()
//     await func2()
// }
// func3()

func1().then(res => {
    func2()
})

;(async () => {
    await func1()
    await func2()
})()

必要商城

https://apifox.com/apidoc/shared-fa9274ac-362e-4905-806b-6135df6aa90e/api-25684707

javascript
// 1. 设置基地址
axios.defaults.baseURL = 'http://123.57.109.30:3999'
// 2. 待会儿事件委托绑定
const oneUl = document.querySelector('#one')
const twoUl = document.querySelector('#two')
const threeUl = document.querySelector('#three')

// 3. 获取一级分类的数据,发请求
;(async () => {
  // 一级分类
  const {data:{list:oneRes}} = await axios.get('/api/categoryfirst')
  console.log(oneRes)
  const htmlArr = oneRes.map(el => {
    return `
        <li data-id=${el.firstId}>${el.firstName}</li>
    `
  })
  oneUl.innerHTML = htmlArr.join('')

  /* ==================== 二级分类的处理 ===================== */
  oneUl.addEventListener('click', async (e) => {
    if (e.target.tagName !== 'LI') return
    const firstId = e.target.dataset.id
    // 发送请求
    const {data:{list:twoRes}} = await axios({
      url:`/api/categorySecond?firstId=${firstId}`,
    })
    // console.log(twoRes)
    const htmlArr = twoRes.map(el => {
      return `
          <li data-id=${el.secondId}>${el.secondName}</li>
      `
    })
    twoUl.innerHTML = htmlArr.join('')
    // 等二级分类有了数据,渲染好了之后,点
    document.querySelector('#two li').click()
  }) // end click

  // 自动click一下,一级分类的第一个li标签
  document.querySelector('#one li').click()
  

  /* ==================== 三级分类的获取 ===================== */

  twoUl.addEventListener('click', async (e) => {
      if (e.target.tagName !== 'LI') return
      const secondId = e.target.dataset.id
      // 发送请求
      const {data:{list:threeRes}} = await axios({
        url:`/api/categoryThird?secondId=${secondId}`,
      })
      // console.log(twoRes)
      console.log(threeRes) 
      const htmlArr = threeRes.map(el => {
        return `
            <li data-id=${el.thiredId}>${el.thiredName}</li>
        `
      })
      threeUl.innerHTML = htmlArr.join('')
  })

})()

Toast轻提示

javascript
const toastBox = document.querySelector('#myToast')
// 生成toast实例
const toast = new bootstrap.Toast(toastBox)

// 想要封装一个tip函数,就是我们自己输入的提示
const tip = (msg) => {
  toastBox.querySelector('.toast-body').innerHTML = msg
  toast.show()
}

注册页

https://apifox.com/apidoc/shared-fa9274ac-362e-4905-806b-6135df6aa90e/api-26239981

javascript
  // 1. 建一个新的分支 git checkout -b m-register
  // 2. 在新分支上做开发,写好功能后,先提交代码,commit
  // 3. 切到master,去合并 git merge m-register
/* ==================== 用户注册功能 ===================== */
const btnRegister = document.querySelector('#btn-register')
const form = document.querySelector('form')

baidu.com  ----> master 
test.baidu.com  ---->  test 
dev.baidu.com   ----->  dev 

btnRegister.addEventListener('click', async () => {
    // 点击按钮的时候,获取输入的username pwd
    const data = serialize(form, {hash:true})
    console.log(data)
    console.log(data.username)
    if (!data.username || !data.password) {
      return tip('账号或密码不能为空哟~🥰~')
    }
    if (data.password.length < 6) return tip('密码长度应该大于6哦~🥰~')

    // 发送请求
    try {
      const res = await axios({
        url:'/register',
        method:'post',
        data
      })
      tip(res.data.message)

      setTimeout(() => {
        location.href = './login.html'
      }, 500);
      // console.log(res)
    }catch(err) {
      tip(err.response.data.message)
      console.dir(err)
    }

    // console.log(res)
})