困扰了很久的异步问题 一般来说,想要 JS 程序顺序执行,会借助 Promise 的链式结构来顺序调用程序
new Promise(resolve => {
Afunc();
resolve(any);
}).then( res=>{
Bfunc();
})
现在我想要做更复杂一点的事,例如 Afunc 里是 react 组件里的一个发请求并 setState 的函数
Afunc = () =>{
axios.post(`xxx`,{params}).then(res=>{
if(res.xxxx === 'xxxx'){
this.setState({},callBackFunc);
}
})
}
我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做,也就是塞在 callBackFunc 里 显然
new Promise(resolve=>{
Afunc();
resolve // resolve 之后不知道多少个 then 才执行 Afunc 里的 .then(res=>{...})
})
不满足我新产生的想法。因为 resolve 的时候 Afunc 只跑到 post, .then 里的代码还没轮到 那么我的问题是,如何在不往 Afunc 里塞 callback 的实现一个可以操控的事件流 我现在的做法
Afunc = (callback) =>{
...
this.setState({},()=>{
callback && callback();
})
}
《 You don't know JS 》里看到的好像是 setTimeout 和 promise 混用的时候,把 resolve 给塞到 setTimeout 中的函数 promise((solve)=>{setTimeout(()=>{func, resolve},1000)}
P.S.(如果要手动实现事件队列那还是算了)
P.S. async/await generator 这些也基于 Promise 的语法糖,真的会有用吗?
1
AlphaTr 2020-02-27 12:43:23 +08:00 via iPhone 1
把 Afunc 包装成 promise
|
2
maichael 2020-02-27 12:44:04 +08:00 1
大概能这么干,但我没有实测。
Afunc = async () => { const res = await axios.post(`xxx`, {params}) if(res.xxxx === 'xxxx') { retrun new Promise(resolve => this.setState({}, resolve)) } } 用的时候直接 await Afunc() otherFunc() 或者 Afunc().then() |
3
crysislinux 2020-02-27 13:03:37 +08:00 1
2 楼的办法就可以了
|
4
kof21411 2020-02-27 13:06:53 +08:00 1
2 楼方法正确,async/await 异步变同步
|
5
azcvcza OP @maichael 和我之前的想法很像,不过如果把 async 打开的话,实际上也是在往 setState 里塞回调
当然这种写法很简洁,受教了 |
6
aaronlam 2020-02-27 13:39:46 +08:00
我现在在项目里基本上用 async await 就能解决很多异步顺序执行的问题
|
7
love 2020-02-27 16:46:29 +08:00
async/await 直观多了,虽然可以做的事回调和 promise 都能做
|
8
TheCZ 2020-02-27 17:36:17 +08:00
这个帖子需要 马克一下 最近遇到同样的疑惑!
|
9
FaiChou 2020-02-27 18:22:56 +08:00 1
@azcvcza #5 「我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做,也就是塞在 callBackFunc 里」显然就需要在 setState({}, callback) 塞回掉了,避免不了的。
所以你的问题答案是: return new Promise(r => this.setState({}, r)) |
10
mmdsun 2020-02-27 18:35:22 +08:00 via Android 1
async/await 可以看一下 msdn 异步文档。async/await 和 Rx 系列,最早都是微软搞出来模型。官方文档很全面。
然后对比学习 coroutine stackful。js 的 async/await 和 fibjs,还有 c#的 async/await,go 的 goroutine。这样异步就不会有什么问题了。 |
12
azcvcza OP @mmdsun 实际上 js 里的 async/await 是包了一层 promise 在里边,我其实真正想知道的是,除了 async/await,和 promise 这系列的顺序流操纵之外,除了往函数参数里塞回调,是不是还会有其他一些通用的,确定异步函数完成时机的东西。当然我自己翻 js 高程,you don‘t know js 没找到这么细的,you don't know 里提到最接近的就是 promise 里塞一个 setTimeout,在 setTimeout 里 resolve 了。生成器看是看了,但平常用的太少
|
14
duan602728596 2020-02-28 00:41:56 +08:00
class Com extends React.Component {
state = { data: [] }; changeData(data) { return new Promise((resolve, reject) => { this.setState({ data }, resolve); }); } async getData() { const res = await fetch(url); const data = await res.data.json(); await this.changeData(data); // 之后要做的事情 } componentDidMount() { this.getData(); } } 根据你的意思写的模拟的代码,就这个意思? |
15
StrayBugs 2020-02-28 01:48:24 +08:00 via Android
你想的方向不对
> 我有一些业务函数(操纵 UI,脏代码)要在 setState 之后才做 react 何时应用更新 states 是不可知的,那么这些副作用应该放到生命周期或者 effect hooks 中处理。 |
16
StrayBugs 2020-02-28 02:07:48 +08:00 via Android
好吧,才发现 setState callback 也是安全的,这么用得比较少,补了个盲点。那么 2 楼是正解。
|
18
azcvcza OP @duan602728596 差不多是这样,你的拆分看起来合适,但本质上还是往里边塞回调了
|