同步与异步
同步,即为等待结果的操作。
// 同步的sleep
function sleep(seconds) {
var start = new Date()
while(new Date() - start < seconds * 1000){}
return
}
// 如下操作在打印出1之后,会等待3秒,然后打印出‘wakeup’,后再打印出2
console.log(1) // 打印出1
sleep(3) // 休眠3秒
console.log('wake up') // 唤醒
console.log(2) // 打印出2
异步,即为不等待结果的操作。
function sleep(seconds, fn) {
setTimeout(fn, seconds * 1000)
}
// 如下操作,打印出1后,会直接打印出2,在三秒之后会打印出‘wakeup’,打印2的操作不会等3秒之后再出现。
// js在打印完1后,告诉浏览器3秒之后打印‘wake up’,js则继续进行接下来的操作,等到3秒后,浏览器会打印出‘wake up’
console.log(1)
sleep(3, ()=>console.log('wake up'))
console.log(2)
前端经常遇到的异步
// 第一次访问的时候没有缓存需要异步下载请求得到图片,第二次访问的时候可以从缓存中读取图片
document.getElementsByTagName('img')[0].width; // 宽度为0
console.log('done')
document.getElementsByTagNames('img')[0].onload = function(){
console.log(this.width) // 宽度不为 0
console.log('real done')
}
console.log('done')
面试中的异步
let liList = document.querySelectorAll('li')
for(var i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(i) // 不管点击哪个,显示的都是6
}
}
// 将循环中的var改成let,则可以点击显示对应的li的下标
// let不会提升作用域,所以每次循环都有一个新的i
Ajax中的异步
let request = $.ajax({
url: '.',
async: false
})
console.log(request.responseText)
$.ajax({
url: '/',
async: true,
success: function(responseText){
console.log(responseText)
}
})
异步的形式
轮询
拿到结果后放到某个地方,定期去看这个地方有没有结果。
function buyFruit() {
setTimeout(()=>{
window.apple = "买到的苹果";
}, Math.Random()*10*1000)
}
buyFruit()
var id = setInterval(()=>{
if(window.apple){
console.log(window.apple);
window.clearInterval(id)
}else{
console.log("桌子上没有水果");
}
}, 1000)
回调
有了结果后,通知我。
function buyFruit() {
setTimeout((fn)=>{
fn.call(undefined, "买到的苹果");
}, Math.Random()*10*1000)
}
buyFruit(function(){
console.log(arguments[0])
})
回调的形式
Node.js的error-list形式
fs.readFile('./1.txt', (error, content)=>{
if(error){
// 失败
}else{
// 成功
}
})
jQuery的success/error形式
$.ajax({
url:'/xxx',
success:()=>{},
error: ()=>{}
})
jQuery的done/fail/always形式
柯里化函数
$.ajax({
url:'/xxx',
}).done( ()=>{} ).fail( ()=>{} ).always( ()=> {})
Promise的then形式
$.ajax({
url:'/xxx',
}).then( ()=>{}, ()=>{} ).then( ()=>{})
// 前面成功return的值可以传给后面的then里面的值
Promise A+规范
axios({
url: 'xxx'
}).then(s1,e1) // 第一责任人
.then(s2, e2) // 第二责任人
.then(s3, e3) // 第三责任人
若axios成功,则s1一定会被调用到; 在s1和e1没有报错的情况下,会调用s2; 在s1或e1报错的情况下,会调用e2。
axios({
url: '',
async: true
}).then((x)=>{
console.log('成功')
return Promise.reject('reject11111')
}, (y)=>{
console.log('失败')
}).then((x)=>{
console.log('成功2')
}, (y)=>{
console.log('失败2')
console.log(y)
})
// 输出结果 成功 失败2 reject11111
如何处理异常??? 出现异常会调用下一个then的error函数 若没有下一个then的error,则错误会抛给开发者,或者写catch函数(相当于一个失败函数)
axios({
url: '',
async: true
}).then((x)=>{
console.log('成功')
return Promise.reject('reject11111')
}, (y)=>{
console.log('失败')
}).then((x)=>{
console.log('成功2')
}).catch((x)=>{
console.log('catch')
console.log(x)
})
// 输出结果 成功 catch reject11111
catch等价于then(undefined, ()=>{}), 相当于一个没有成功函数只有失败函数的then
自己写Promise
buyFruit(){
return new Promise((x, y)=>{
setTimeout(()=>{
x('apple')
}, 1000)
})
}
var promise = buyFruit()
promise.then(()=>{console.log(1)}, ()=>{console.log(2)})
function buyFruit(){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('apple')
}, 10000)
})
}
var promise = buyFruit()
promise.then(()=>{console.log(1)}, ()=>{console.log(2)})