You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 14.1与16.x中Promise.resolve().then()执行顺序差异排查及解决

不同iOS版本下Promise回调执行顺序差异问题解析

测试代码

const resolve = Promise.resolve()
function run() {
  try {
    try {
      
    console.log(1)
    resolve.then(() => {
      console.log(resolve, 2)
    })
    console.log(3)
    } finally {
      console.log(4)
    }
  } catch (e) {
    console.log(e)
  }
  console.log('return')
}
run()

不同iOS版本的执行结果

  • iOS 14.1 输出:
1
3
2
4
return
  • iOS 16.x 输出:
1
3
4
return
2

问题

为何会出现这种情况?该问题的根本原因是什么,又该如何解决?


根本原因

这是iOS不同版本搭载的JavaScriptCore(WebKit内置JS引擎)对已决议Promise的then回调处理逻辑不一致导致的:

  • iOS 14的旧版引擎中,调用已决议Promise的then时,回调会被插入到微任务队列的队首,优先级高于当前执行栈中待执行的同步代码(比如finally块),导致回调在finally之前触发。
  • iOS 16的新版引擎修正了这个行为,严格遵循ECMAScript标准:已决议Promise的then回调会被正常加入微任务队列末尾,必须等当前执行栈中的所有同步代码(包括finally块、函数末尾的console.log('return'))执行完毕后,才会依次执行微任务队列中的回调。

本质是旧版引擎的实现不符合ES标准,新版做了标准对齐。

解决方法

要让代码在所有iOS版本中保持一致的执行顺序,需保证Promise回调的执行时机符合标准,推荐两种方案:

方案一:用新Promise包裹,强制标准异步顺序

将已决议Promise的回调逻辑放入新的Promise.resolve()的then中,确保回调进入正确的微任务队列顺序:

const resolve = Promise.resolve()
function run() {
  try {
    try {
      console.log(1)
      // 用新Promise包裹,让回调按标准微任务顺序执行
      Promise.resolve().then(() => {
        resolve.then(() => {
          console.log(resolve, 2)
        })
      })
      console.log(3)
    } finally {
      console.log(4)
    }
  } catch (e) {
    console.log(e)
  }
  console.log('return')
}
run()

修改后所有版本都会输出:

1
3
4
return
2

方案二:明确同步与异步边界

如果需要调整回调的执行位置(比如在finally之后、return之前),可以显式控制代码顺序,比如将finally的部分逻辑或回调逻辑放入微任务队列,但这种场景下方案一更直接有效。


内容的提问来源于stack exchange,提问作者Menyou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:41:29