JS嵌套ajax+setInterval,怎样改成同步请求?

怎样让下面这段代码变成同步,顺序的打印出1 0 0 0 2 0 0 0 3 0 0 0 4 5

func() {

console.log(1)

const arr = [2, 3, 4]

arr.forEach((num, idx) => {

this.$http.get('a-url').then(() => {

const interval = setInterval(() => {

let i = 0

this.$http.get('b-url').then(() => {

i = i + 1

console.log(0)

if(i === 3) {

clearInterval(interval)

}

})

}, 1000)

})

console.log(num)

})

console.log(5)

}


回答:

async func() {

console.log(1)

const arr = [5, 6, 7]

for (const num of arr) {

await this.$http.get("a-url");

let i = 1;

await new Promise((resolve, reject)=>{

const interval = setInterval(async () => {

i = i + 1

await this.$http.get("b-url")

num<6&&console.log(i)

if(i === 4) {

clearInterval(interval)

resolve()

}

}, 1000)

})

console.log(num)

}

console.log(8)

}


回答:

新问题就简单很多了,但是因为是使用 forEach() 所以就不能直接使用 async/await 了,得使用 Promise 来配合,但是代码会比较复杂,所以如果可以改成 for 循环的话,就可以使用 async/await 了,代码会精简很多:

async function fn(){

console.log(1)

const arr = [2, 3, 4]

for(const num of arr){

// 等待A请求完成

await getAction('a-url')

// 等待B请求完成,并输出 3 次 0

await new Promise((resolve) => {

let i = 0 // 题目中声明的位置错误会造成死循环,所以调整了位置

const interval = setInterval(() => {

getAction('b-url').then(() => {

i = i + 1

console.log(0)

if(i === 3) {

clearInterval(interval)

resolve() // 完成 Promise

}

})

}, 1000)

})

console.log(num)

}

console.log(5)

}

fn()

// 假请求函数

function getAction(url){

return new Promise((resolve) => {

setTimeout(() => { resolve() }, 300)

})

}


正常业务场景里面是不会遇到这样的情况的,所以基本就是面试题,而且还是专门来为难面试者的了。

因为中间输出的 234 是重复输出,在浏览器控制台看似时输出了 2 3 4 但其实是合并后的,也就是输出的 2 2 2 3 3 3 4 4 4
所以不能简单使用 async/await 来同步执行,所以依旧使用 Promise 来实现。

魔改了代码,以便可以直接在浏览器控制台输出:

function fn(){

console.log(1)

const arr = [5, 6, 7]

// 需要异步全部执行完毕之后输出 8 ,所以需要使用到 `Promise.all`

Promise.all(arr.map(num => {

return new Promise((resolve1) => {

getAction('a-url').then(() => {

// 中间输出的 2,3,4 是重复输出,也就是输出的 2,2,2,3,3,3,4,4,4

// 所以不能简单使用 `async/await` 来同步执行,所以依旧使用 `Promise`

const tmp = () => {

return new Promise((resolve2) => {

// 正常 A 请求完毕之后业务代码

let i = 1;

const interval = setInterval(() => {

i = i + 1

getAction('b-url').then(() => {

console.log(i)

if(i === 4) {

clearInterval(interval)

// 这里是个坑,直接 resolve 会有微任务插队的问题

setTimeout(() => resolve2(),0)

}

})

}, 1000)

})

}

// 2,2,2,3,3,3,4,4,4 输出完毕之后输出 num

tmp().then(() => {

console.log(num)

resolve2()

})

})

})

})).then(() => {

// 全部输出完毕后输出 8

console.log(8)

})

}

fn()

// 假请求函数

function getAction(url){

return new Promise((resolve) => {

// 异步事件不能过长,不然会超过 B 请求时 1000ms 的定时器,输出顺序会错位。

setTimeout(() => { resolve() }, 200)

})

}

以上是 JS嵌套ajax+setInterval,怎样改成同步请求? 的全部内容, 来源链接: utcz.com/p/933573.html

回到顶部