十五分钟了解异步解决方案

156 阅读3分钟

前言

javascript 是单线程; 浏览器是多线程;所有异步解决方案归根结底都是回调形式。

1.Promise基本使用及本质

let p1 = new Promise((resolve, reject) => {
    let arr = [1,2,3,4,5];
    let arr1 = arr.filter(item => item > 3);
    setTimeout(() => {
        resolve(arr1);
    }, 1000)
})
p1.then(res => {
    console.log(res);
},err => {
    console.log(err);
})
  • promise本质上是一个状态机,他的状态变化时单向的,也就是说他只能从pending(等待中)->resolve(已完成fulfilled),或者pending->rejected(已拒绝);

  • then方法有两个参数,分别对应两种改变后状态(resolve)和(reject)

2.then链式调用

const p1 = new Promise((resolve, reject) => {
  let arr = [1,2,3,4,5];
    let arr1 = arr.filter(item => item > 3);
    setTimeout(() => {
        resolve(arr1);
    }, 1000)
})

p1
  .then(res => {
    console.log(res)
    //then回调中可以return一个Promise
    return new Promise((resolve, reject) => {
      let arr2 = [1,2,3];
      setTimeout(() => {
        resolve(arr2)
      }, 1000);
    })
  })
  .then(res => {
    console.log(res)
    //then回调中也可以return一个值
    return 1
  })
  .then(res => {
    console.log(res)
  })

//
//[4,5];
//[1,2,3];
//1

3.async/await基本使用

在处理多个彼此之间相互依赖的请求时候,promise的then方法显得过于累赘,此时用async/await就很轻便。

使用方法:

  • 在函数前添加async,则在函数执行后自动返回一个Promise对象。
//eg1:
async function Person() {
    
}
let result = Person()
console.log(result);
//虽然Person方法无返回值,但result打印结果时Promise对象
//Promise {<resolved>: undefined}
//->__proto__: Promise
//->[[PromiseStatus]]: "resolved"
//->[[PromiseValue]]: undefined


//eg2:
async function Person() {
    return 2
}
let result = Person()
console.log(result);// Promise {<resolved>: 2}
//Promise {<resolved>: 2}
//->__proto__: Promise
//->[[PromiseStatus]]: "resolved"
//->[[PromiseValue]]: 2
  • await 必须在async函数里面使用,不能单独使用。
async function Person() {
    let result = await Promise.resolve('success')
    console.log(result)
}
Person()
  • await 后面需要跟随Promise对象,不然没有意义,此时Promise对象后面不需要写then了, 因为await作用就是获取Promise对象的成功状态传递出的参数
function ret() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        })
    })
}

async function test() {
    let result = await ret() //因为fn会返回一个Promise对象
    console.log(result)    //这里会打出Promise成功后传递过来的'success'
}

test()

4.async/await错误处理方式

关于错误处理,由于await接受的是Promise成功状态的参数,则需要用到try catch来捕捉错误。

function ret (num){
  return new Promise((resolve, reject) => {
    setTimeout(() => {
        if (num >= 100) {
            resolve('success')
        } else {
            reject('failed')
        }   
    }, 1000)
	})
}

async function test() {
    let result = await ret(222)
    return result  //由于await接受的是Promise成功状态的参数,如果失败了,跳到catch
}

test().then(response => {
    console.log(response) 
}).catch(error => {
    console.log(error)
})

async/await

在async函数中使用await,那么await里面的代码就是同步,只有等await后面的Primise代码执行完,才可以继续往下一行执行,虽然同步代码,但也阻塞代码。

function fn(name) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`${name}成功`)
        }, 1000)
    })
}

async function test() {
    let p1 = await fn('小红')
    let p2 = await fn('小明')
    let p3 = await fn('小华')
    return [p1, p2, p3]
}

test().then(result => {
    console.log(result)
}).catch(result => {
    console.log(result)
})

Demo

promise

function request(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time)
        }, time)
    })
}

request(500).then(result => {
    return request(result + 1000)
}).then(result => {
    return request(result + 1000)
}).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
}) 

转换成async/await

function request(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time)
        }, time)
    })
}

async function getResult() {
    let p1 = await request(500)
    let p2 = await request(p1 + 1000)
    let p3 = await request(p2 + 1000)
    return p3
}

getResult().then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})