JavaScript 异步编程
大约 3 分钟
JavaScript 异步编程
callback函数
promise
ES10 - asyn - await
踩坑
callback回调函数
调用函数
function functionA(callbake){}
functionA(()=>{})
会识别为传入的是一个对象
改法:
function functionA(null, callbake){}
functionA(null,()=>{})
原因好像是因为第一个必须是Error,就算没有也要返回null
便于错误后不调用callback
promise执行顺序
then里嵌套的then优先级少于该then同级往下!即:
.then(()=>{
// 执行1
.then(()=>{
// 执行3
})
.then(()=>{
// 执行4
})
})
.then(()=>{
// 执行2
})
【总结、比较、原理、写法互转】
比较then和aysnc-await
(以下函数,都优化成能直接在控制台运行,可以方便调试)
// 异步函数A
// 输出顺序:
// a0.start -> a0.returnFake -> a0.2s
let getPromise = ()=>{
return new Promise((resolve, reject) => {
console.log("a0. start")
setTimeout(() => {
console.log("a0. 2s")
resolve("a0. returnTrue")
}, 2000);
console.log("a0. returnFake")
});
}
getPromise()
// 函数B调用异步函数A - then方案
// 输出顺序:
// b1.start -> a0.start -> a0.returnFake -> b1.return -> a0.2s -> b1.getReturn: a0.returnTrue
let b1 = ()=>{
console.log("b1. start") // 1
getPromise().then((item)=>{ // 外2, 内4
console.log("b1. getReturn: ", item) // 5
})
console.log("b1. return") // 3
}
b1()
// 函数B调用异步函数A - await方案
// 输出顺序:
// b2.start -> a0.start -> a0.returnFake -> a0.2s -> b2.getReturn: a0.returnTrue -> b2.return
let b2 = async ()=>{
console.log("b2. start") // 1
let item = await getPromise() // 外2, 内3
console.log("b2. getReturn: ", item) // 4
console.log("b2. return") // 5
}
{
console.log("b3. start") // 0.5
b2() // 见上
console.log("b3. over") // 2.5
}
本质是一样的
在同步函数调用Promise函数的场景中,比较区别:
- setTimeout相当于多了一条线程在工作,与主线程无关,主线程没有方法获取子线程的返回值
- Promise-Then方案,相当于往子线程传递一个回调函数,回调函数对应的是
then(...)
里面的内容! - Async-Await方案,相当于往子线程传递一个回调函数,回调函数对应的是
await ...
该行代码的往下的所有内容!
(当然,在js中,其实这是伪的多线程,只是类比好说明)
主线程如何获取子线程的返回值?
promise和await方案,都没有真正做到这一点。
……如果按其他语言的思路,那么就是利用线程之间的共享变量来做到
当我发现,做不到
// 异步函数A
// 输出顺序:
// 尝试:待变动 -> 尝试:变动了
let promiseChange = (global)=>{
return new Promise((resolve, reject) => {
console.log("尝试:待变动", global)
setTimeout(() => {
global.flag = 1;
console.log("尝试:变动了", global)
}, 2000);
});
}
promiseChange(global)
// 函数B调用异步函数A - then方案
// 输出顺序:
// 预期:尝试:待变动 -> 检测:未变动 -> 检测:未变动 -> 尝试:变动了 -> 检测:变动了
// 实际:尝试:待变动 -> 检测:未变动 -> 检测:未变动 -> ... -> 尝试:变动了
// 失败分析:
// 看起来js的 `delay` 把setTimeout线程也给一起延时了,可能是因为js的setTimeout不是真正的多线程?
let global = {
flag: 0
};
let c = ()=>{
promiseChange(global)
for (let i = 0; i<10; i++) { // 10s超时
if (global.flag == 0) {console.log("检测:未变动", global); }
else {console.log("检测:变动了", global); break; }
delay(1000)
}
}
c()
不要擅自帮我修改成then和await方法,假设函数c是一个接受number变量的回调函数,在无法修改函数c参数类型的前提下,我在尝试是否有可能能让c返回一个number变量
……感觉没什么方法,同步调用异步 这一行为,在其他语言中可能我能想一些骚操作能做到。反正js中可能只能老老实实用promise和await了