异步同步化

异步同步化

ES6前

回调地狱

当出现请求之间相互依赖时,就往往出现这种回调地狱,维护起来非常难受

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$.ajax(
{
url: 'https://ku.qingnian8.com/dataApi/news/navlist.php',
type: 'GET',
success: resp => {
let id = resp[0].id
$.ajax(
{
url: 'https://ku.qingnian8.com/dataApi/news/newslist.php',
type: 'GET',
data: {
cid: id
},
success: resp => {
let id = resp[0].id
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/comment.php',
type: 'GET',
data: {
aid: id
},
success: resp => {
console.log(resp)
}
})
}
}
)
}
}
)

封装回调

封装回调本质上和写在一起都是一样的, 只不过看起来比较清晰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const getNav = (callback: (res: any) => void) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/navlist.php',
type: 'GET',
success: resp => {
callback(resp)
}
})
}

const getArticle = (callBack: (res: any) => void, id: number) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/newslist.php',
type: 'GET',
data: {
cid: id
},
success: resp => {
callBack(resp)
}
})
}

const getComment = (callBack: (res: any) => void, id: number) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/comment.php',
type: 'GET',
data: {
aid: id
},
success: resp => {
callBack(resp)
}
})
}

// 主体
getNav(
res => {
let id = res[0].id
getArticle(res1 => {
let id = res1[0].id
getComment(res2 => {
console.log(res2)
}, id)
}, id)
}
)

ES6后

Promise

promise是解决异步的方法,本质上是一个构造函数,可以用它实例化一个对象。对象身上有resolve、reject、all,原型上有then、catch方法。promise对象有三种状态:pending(初识状态/进行中)、resolved或fulfilled(成功)、rejected(失败)

  1. pending。它的意思是 “待定的,将发生的”,相当于是一个初始状态。创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。
  2. resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法。
  3. rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数。

promise.png

使用Promise包起来后,再链式调用,就很优雅了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const getNav = (): Promise<any> => {

return new Promise((resolve, reject) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/navlist.php',
type: 'GET',
success: resp => {
resolve(resp)
},
error: err => {
reject(err)
}
})
})
}

const getArticle = (id: number): Promise<any> => {

return new Promise((resolve, reject) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/newslist.php',
type: 'GET',
data: {
cid: id
},
success: resp => {
resolve(resp)
},
error: err => {
reject(err)
}
})
})


}

const getComment = (id: number): Promise<any> => {

return new Promise((resolve, reject) => {
$.ajax({
url: 'https://ku.qingnian8.com/dataApi/news/comment.php',
type: 'GET',
data: {
aid: id
},
success: resp => {
resolve(resp)
},
error: err => {
reject(err)
}
})
})

}

// Promise的链式调用
getNav().then(res => {
let id = res[0].id
return getArticle(id)
}).then(res => {
return getComment(res[0].id)
}).then(res => {
console.log(res)
})

ES7

await / async ES7的新规范,异步处理同步化

这两个命令是成对出现的,如果使用await没有在函数中使用async命令,那就会报错,如果直接使用async没有使用await不会报错,只是返回的函数是个promise,可以,但是没有意义,所以这两个一起使用才会发挥出它们本身重要的作用。所谓异步同步化感觉就是将一些需要异步执行的任务放在一起让他们同步。

1
2
3
4
5
6
7
8
9
10
11
const onload = async () => {
let res, id
res = await getNav()
id = res[0].id
res = await getArticle(id)
id = res[0].id
res = await getComment(id)
console.log(res)
}

onload()

使用axios请求时已经封装好了Promise,更方便

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const getNav = (): Promise<any> => {
return get('https://ku.qingnian8.com/dataApi/news/navlist.php')
}
const getArticle = (id: number): Promise<any> => {
return get('https://ku.qingnian8.com/dataApi/news/newslist.php', {cid: id})
}
const getComment = (id: number): Promise<any> => {
return get('https://ku.qingnian8.com/dataApi/news/comment.php', {aid: id})
}

const onload = async () => {
let res, id
res = await getNav()
id = res[0].id
res = await getArticle(id)
id = res[0].id
res = await getComment(id)
console.log(res)
}

onload()

封装的axios

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import type {AxiosRequestConfig, Method} from 'axios'
import axios from "axios";


const service = axios.create({
baseURL: 'https://ku.qingnian8.com',
timeout: 5000
})

// 处理响应拦截器
service.interceptors.response.use(response => response.data)


// axios中的ts认为data是有的,但是响应拦截器实际已经去掉了

type Data<T> = {
code: number
message: string
data: T
}

const request = <T>(url: string, method: Method, submitData?: object, config?: AxiosRequestConfig) => {
return service.request<T, Data<T>>({
url,
method,
[method.toLowerCase() === 'get' ? "params" : "data"]: submitData,
...config
})
}

export const get = (url: string, submitData?: object, config?: AxiosRequestConfig) => {
return request(url, 'get', submitData, config)
}

export const post = (url: string, submitData?: object, config?: AxiosRequestConfig) => {
return request(url, 'post', submitData, config)
}

export default request

异步同步化
http://example.com/2023/09/06/异步同步化/
作者
ykexc
发布于
2023年9月6日
许可协议