vue关于循环请求接口,接口并发产生的报错问题

当有一种需求需要循环调用接口时,由于并发产生的问题,正常的foreach循环由于是同步进行只能成功一次后续都失败

const postArr = [
    {
        id: 1,
        age:12,
        name: 'xiaohong'
    },
    {
        id: 2,
        age:12,
        name: 'xiaohong1'
    },
    {
        id: 3,
        age:12,
        name: 'xiaohong2'
    },
]
const newData = []

const postApi = () => {
//请求接口
    postArr.forEach(item => {
       apiAdd(item).then(res=> {
            newData.push(res.data)
        }) 
    })
} 

只可以成功一次

正确使用-直接复制即可

/**task.js
 * @param {每次同时执行的任务数量} parallelCount
 */

class SuperTask {
  constructor(parallelCount = 1) {
    this.parallelCount = parallelCount
    this.tasks = []
    this.runingCount = 0
  }
  add(task) {
    return new Promise((resolve, reject) => {
      this.tasks.push({
        task,
        resolve,
        reject
      })
      this._run()
    })
  }

  _run() {
    while (this.runingCount < this.parallelCount && this.tasks.length) {
      const { task, resolve, reject } = this.tasks.shift()
      this.runingCount++
      Promise.resolve(task())
        .then(resolve, reject)
        .finally(() => {
          this.runingCount--
          this._run()
        })
    }
  }
}

export const superTask = new SuperTask()

使用

<template>
    <div>
        <el-button @click="generateYD">开始请求</el-botton>
    </div>
</template>
<script setup>
import { superTask } from '../task.js'

const postArr = [
    {
        id: 1,
        age:12,
        name: 'xiaohong'
    },
    {
        id: 2,
        age:12,
        name: 'xiaohong1'
    },
    {
        id: 3,
        age:12,
        name: 'xiaohong2'
    },
]

const newData = []

const generateYD = () => {
    postArr.forEach(item=> {
        addTask(item)
    })
}

const breakReserve = (item) => {
        return new Promise((resolve, reject)=> {
           //上传接口
            postReserve(item).then(res=> { 
                resolve(res) //抛出结果
            })
        })
    }

const addTack = (item)=> {
    //每次请求成功得到结果之后继续请求下一个,直到结束
    superTask.add(()=>breakReserve(item)).then(res=>{
        //console.log(res) 每请求一次放回一次结果
        newData.push(res.data)
    })
}
</script>

<think>嗯,用户想知道如何正确使用JavaScript中的await关键字。首先,我得回忆一下关于async/await的基础知识。记得await只能在async函数内部使用,否则会报错。这应该是第一个要点。然后,用户可能想知道await如何处理不同的返回值,比如普通值、Promise对象,或者thenable对象。引用[1]提到,如果await后面是一个普通的值,会直接返回,如果是thenable对象,会根据then方法调用来决定后续的值。而如果返回的Promise是reject状态,就会抛出异常。这些都需要详细说明。 接下来,用户可能关心错误处理。使用try...catch来捕获await表达式中的错误,这很重要。引用[2]中的示例二展示了如何用try...catch处理错误,所以应该包括这部分内容。另外,并发执行的问题,比如使用Promise.all来优化多个异步操作的并行执行,如引用[4]中的例子,这样可以避免不必要的等待时间,提高效率。 还要注意常见的误区,比如在非async函数中使用await会导致语法错误,或者在循环中错误地使用顺序await,导致性能问题。比如在循环中每次使用await,会导致每个迭代等待完成,而不是并行执行。这时候应该用Promise.all来处理多个异步任务。 另外,用户可能在实际使用中遇到问题,比如在Vue项目中导出方法时的错误,如引用[5]提到的导出方法时错误地调用了函数,导致问题。这可能是一个常见的陷阱,需要提醒用户注意。 最后,给出一些使用建议,比如优先在async函数中使用,合理处理并发,以及错误处理。同时,生成相关问题,帮助用户进一步学习,比如await和then的区别,如何提升性能,处理多个异步任务的最佳实践等。 总结一下,回答的结构应该包括基本用法、返回值处理、错误处理、并发执行、常见误区和使用建议。每个部分都要结合引用中的例子,确保信息准确,并且符合用户的实际需求。同时,保持语言简洁明了,结构清晰,帮助用户一步步理解如何正确使用await关键字。</think>### 如何正确使用 JavaScript 中的 `await` 关键字? #### 一、基本使用条件 1. **必须在 `async` 函数中使用** `await` 关键字只能出现在声明为 `async` 的异步函数内部,否则会触发语法错误。例如: ```javascript async function fetchData() { const result = await somePromise; // 正确 } function normalFunc() { const result = await somePromise; // ❌ SyntaxError: await is only valid in async function } ``` 2. **与 Promise 的协作** `await` 的主要作用是**暂停异步函数执行**,等待 Promise 状态变为 `fulfilled` 或 `rejected`,并返回结果。例如引用[1]中的示例: ```javascript async function foo() { const res1 = await bar(); // 等待 bar() 的 Promise 完成 console.log("await后面的代码:", res1); // 等待2秒后执行 } ``` --- #### 二、返回值处理规则 1. **普通值** 如果 `await` 后是普通值(非 Promise),则直接返回该值: ```javascript async function demo() { const num = await 42; // 直接返回42 console.log(num); // 42 } ``` 2. **Promise 对象** 如果 `await` 后是 Promise,函数会暂停执行,直到 Promise 状态变化: - **成功**:返回 `resolve` 的值 - **失败**:抛出 `reject` 的异常(需通过 `try...catch` 捕获) 3. **Thenable 对象** 如果对象实现了 `.then()` 方法(如 jQuery Deferred),会按照 Promise 规范处理。例如: ```javascript const thenable = { then: function(resolve) { resolve('thenable resolved'); } }; async function demo() { const result = await thenable; // 输出 'thenable resolved' } ``` --- #### 三、错误处理机制 必须使用 `try...catch` 捕获 `await` 可能抛出的异常,如引用[2]示例二所示: ```javascript async function errorExample() { try { let response = await fetch('https://api.example.com/invalid-url'); if (!response.ok) throw new Error('请求失败'); let data = await response.json(); } catch (error) { console.error('捕获到错误:', error); } } ``` --- #### 四、并发执行优化 若需要并行执行多个异步操作,应使用 `Promise.all` 而非顺序 `await`,如引用[4]示例: ```javascript async function concurrentDemo() { const [res1, res2] = await Promise.all([fetch(url1), fetch(url2)]); // 两个请求同时发起,总时间取决于最慢的请求 } ``` --- #### 五、常见误区与解决方案 | 误区场景 | 错误示例 | 正确写法 | |---------|---------|---------| | 在非 `async` 函数中使用 `await` | `function bar() { await somePromise; }` | 添加 `async` 关键字:`async function bar()` | | 循环中顺序等待导致性能问题 | `for(const url of urls) { await fetch(url) }` | `await Promise.all(urls.map(url => fetch(url)))` | | 忽略错误处理 | `const data = await fetch();` | 用 `try...catch` 包裹 | --- #### 六、使用建议 1. **优先在 `async` 函数中使用**:确保代码结构清晰 2. **合理处理并发**:根据场景选择顺序执行(`await` 串联)或并行执行(`Promise.all`) 3. **错误边界明确**:通过 `try...catch` 或 `.catch()` 处理异常 --- 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值