1.什么时候需要回调函数?
什么时候需要使用回调函数?比如在JavaScript中,我们需要向服务端request一个请求,这可能花费几秒钟来等待数据返回,我们没有必要硬等数据,而可以先干别的事,这时候回调函数(Callbacks)就可以派上用场了。下面通过一个和服务器或数据库交互的例子展现他们的使用:
const posts = [
{title: 'Post One', body: 'This is post one'},
{title: 'Post Two', body: 'This is post two'}
]
function getPosts() {
setTimeout(()=>{
let output = ''
posts.forEach((post, index)=>{
output += `<li>${post.title}</li>`
})
document.body.innerHTML = output
},1000)
}
setTimeout(()=>{},1000)是一个基本的回调函数,它可以让我们在1秒之后再执行所需的函数(注意:表示模板语法需要使用反括号,所以在forEach循环中我们需要使用反括号``)。
执行这个函数,我们会发现posts数组中的两条数据在1秒之后成功显示。
getPosts()
因为我们需要和服务器交互,所以需要有添加功能。于是接着创建一个添加函数,这次我们设置为2秒的setTimeout()。
function createPost(post){
setTime(() => {
post.push(post)
},2000)
}
createPost({title:'Post Three', body: 'This is post three'})//函数调用形式
2.Callbacks
我们在createPost()中添加一个callback参数,这个参数你想叫什么都可以,为了方便表示直接设置为'callback'。
function createPost(post, callback){
setTimeout(() => {
posts.push(post)
callback()
},2000)
}
这个callback参数的作用就是紧接着post.push之后要干的事,于是我们把上面定义的getPosts传入createPost中:
createPost({title:'Post Three', body: 'This is post three'},getPosts)
在浏览器执行createPost,你会发现三个数据都被添加进去,并且一同被显示了出来。他的执行逻辑是首先等待2秒之后执行posts.push(post),之后等待1秒执行getPosts(),这样你就对回调函数有了一个基本理解。
3.Promise
Promise是为了解决回调地狱而在ES6新增的函数,在英语里promise的意思是约定,我们可以形象理解为答应了朋友要干一件事就是promise。Promise有resolve,reject两种状态。见名知意,resolve代表Promise成功解决,reject代表发生了一些错误导致失约了。
下面我们把createPost函数从Callback形式改成Promise形式,把它从“地狱”中拉回来。
function createPost(post){
return new Promise(
(resolve, reject) => {
setTimeout(() => {
posts.push(post)
const error = false
if (!error) {
resolve()
} else {
reject('Error: Something went wrong')
}
},2000)
}
)
}
之后就是调用函数了,在Promise中使用Promise.then()方法来回调:
createPost({title:'Post Three', body: 'This is post three'})
.then(getPosts)
我们后续想要写更多的回调函数,只需要在.then()方法后面继续加.then()就行:
createPost({title:'Post Three', body: 'This is post three'})
.then(getPosts)
.then(XXX)
.then(YYY)
.then(...)
3.Async Await
在ES7中新增了Async,Await,它的意义是使我们能更加方便的用Promise。
继续我们的例子,我们不对Promise版的createPost进行修改,还是继续沿用:
function createPost(post){
return new Promise(
(resolve, reject) => {
setTimeout(() => {
posts.push(post)
const error = false
if (!error) {
resolve()
} else {
reject('Error: Something went wrong')
}
},2000)
}
)
}
接着使用Async,Await新建一个init函数,这个函数声明前加上async,在init函数内需要被等待的函数前加上await,意思就变成了先等createPost执行完毕,然后执行getPosts:
async function init() {
await createPost({title:'Post Three', body: 'This is post three'})
getPosts()
}
init是封装好的函数,我们还要调用它:
init()
Promise还有一些具体方法,再学习一段时间继续总结。