JS技术疑问:链式then需添加return,嵌套then为何无需?
我需要按顺序执行一系列API调用(前一个完成后再执行下一个),于是把原本嵌套then的代码改成链式then的形式,却发现链式then里必须加return,嵌套then则不需要,对此存在疑问。
重构前(嵌套then写法)
axios.get('https://example.com', {}) .then(function (responseOne: any) { axios.post('https://example.com', {}, {}) .then(function (responseTwo: any) { axios.put('https://example.com', {}, {}) .then(function (responseThree: any) { axios.post('https://example.com', {}, {}) .then(function () { reply.send }) }) }) })
重构后(链式then写法)
axios.get('https://example.com', {}) .then(function (responseOne: any) { return axios.post('https://example.com', {}, {}) }).then(function (responseTwo: any) { return axios.put('https://example.com', {}, {}) }).then(function (responseThree: any) { return axios.post('https://example.com', {}, {}) }).then(function () { reply.send })
原因解析
核心在于Promise的then方法的工作机制:
嵌套then的逻辑:你在第一个then的回调里直接调用
axios.post,这个post请求会返回一个新的Promise,后续的then都是挂在这个新Promise上的。外层的then回调没有return任何值,所以外层then会默认返回一个状态为resolved、值为undefined的Promise,但内层的then链完全不依赖这个外层Promise,它只跟着axios.post返回的Promise走,所以依然能按顺序执行。但这种写法本质是回调嵌套,不是真正的链式调用。链式then的逻辑:链式调用的关键是让每一个
then返回下一个要执行的Promise。因为链式里的下一个then是挂载在当前then返回的Promise上的,如果不return,当前then会默认返回一个resolved的Promise,下一个then会立刻执行,根本不会等待axios的请求完成,直接导致API调用变成并行,完全破坏了顺序执行的要求。只有return了axios请求返回的Promise,下一个then才会等待这个请求完成后再触发。
简单总结:嵌套写法里后续then绑定的是新请求的Promise;链式写法里后续then绑定的是当前then返回的Promise,所以必须return下一个请求的Promise才能保证顺序执行。
内容的提问来源于stack exchange,提问作者userMod2

