在js中,怎么处理异步代码
1. 封装函数并使用回调函数
例子请看本博客里边的原生js实现ajax
但是使用这种回调函数,很容易出现回调地狱。比如我先执行了一个异步代码,然后
再执行异步代码就需要在回调函数中去执行,这样会陷入**回调地狱**
2. 使用promise
在使用promise前,了解一下promise。
promise的出现,可以解决上边我们说的回调地狱的问题。因为promise是链式调用。
promise的三种状态:
◆ pending ----- 进行中
◆ resolve ----- 成功
◆ reject ----- 失败
promise对象,可以将异步操作以同步操作的流程表达出来,这样就避免的回调函数的层层嵌套的地域般的回调。
但是promise对象的状态不受外界影响,promise对象代表一个异步操作,有三种状态。只有异步操作的结果,可以
决定当前是哪一种状态,任何其他操作都不能改变这个状态,这也是promise的名字的由来。“承诺”表示其他手段都
无法改变状态
状态的改变不可逆转,一旦决议就不能再更改。所以promise的状态改变只有两种:
◆ pending(进行中)----> resolve(成功)
◆ pending(进行中)----> reject(失败)
setTimeout(function(){console.log(1)},0)
new Promise(function(resolve,reject){
setTimeout(function(){
console.log(2)
resolve()
},0)
console.log(3)
}).then(function(){
console.log(4)
})
console.log(5)
上述代码的结构是35124。js中首先执行的代码永远是同步代码,即console.log(3)和console.log(5)是最先执行的,按
照从上到下的顺序执行。异步代码是在同步代码执行完成后执行(异步代码存放在异步队列中,遵循先进先出),所
以先后执行的是console.log(1)和console.log(2)。then的回调函数会在当前脚本任务执行完成后执行,所以最后执行
concole.log(4)
通过上边代码演示,我们可以清楚的知道在我们想要先执行异步代码后,再执行一些同步代码,但是不想用回调函数
可以使用promise
//promise 的链式操作
new Promise(function(resolve,reject){}).then().then()...
//promise 捕获异常
const promise = new Promise(function(resolve, reject) {
try {
throw new Error('test');
} catch(e) {
reject(e);
}
});
promise.catch(function(error) {
console.log(error);
}
当我们需要同时执行多个异步代码时,可以使用promise.all。成功后会返回一个数组,数组值是按照请求时的顺序,失败会返回最先的reject 的值
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promise.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
3. 使用async/await
function test1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
}
function test2 (val) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(val)
resolve(2)
}, 2000)
})
}
async function asyFun(){
try{
console.log(1111)
let t1 = await test1()
let t2 = await test2(t1)
console.log(t2)
}catch(err){console.log(err)}
}
一般我们使用async/await组合是执行多个异步代码,并且这几个异步代码之间有依赖关系。如果没有依赖关系可以直接使用promise.all。因为考虑到性能问题。await后的代码需要的async函数中使用