添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

for循环请求接口异步怎么赋值呢?

头像
CaixK
575 24 334 654

需求:for循环数组 arr 调用同一接口传入不同 id 获取图片路径赋值到url上,再用 arr 渲染列表
遇到的问题: getUrl() 中怎么把res返回出来,还有 getUrl 异步的是不是不能直接 i.url = getUrl(i.id)
请巨佬指点一下

arr = [
        id:'xxx'
        name:"xxx",
        url:""
        id:'xxx'
        name:"xxx",
        url:""
function getUrl(id) {
  getFileUrl(id).then(res=>{
        console.log(res) // 图片路径
arr.forEach(i=>{
    i.url = getUrl(i.id)
})
前端 javascript vue.js
阅读 2.7k
2 个回答
社区维基
1
✓ 已被采纳

异步已经脱离了原来的执行顺序,需要在新的“异步”顺序中执行代码。建议你先看看 ——

异步编程需要“意识” - SegmentFault 思否

既然 getFileUrl 是一个异步方法,可以使用回调或者 Promise 来组织“异步顺序”。如果想按同步的写法来写,可以使用 async/await 语法,参考:

理解 JavaScript 的 async/await - SegmentFault 思否

就这个问题,看 getFileUrl 的写法,应该是返回的一个 Promise,不需要再封一个 getUrl ,可以改写代码如下(大致)

for (const it of arr) {
    getFileUrl(it.id).then(url => it.url = url);
}

或者使用 await 写法,下面这种写法不会同时发起异步处理,会一个一个的去发起并处理完成。但 IIFE 本身会立即返回(返回的是一个 Promise,丢掉了,没使用)

(async () => {
    for (const it of arr) {
        it.url = await getFileUrl(it.id);
})();

虽然一般处理异步的循环都应该使用 for ... in/of,而不使用 forEach() ,但这里因为你不需要等全部返回,所以用 forEach 也是可以的

arr.forEach(it => getFileUrl(it.id).then(url => it.url = url));

如果要封 getUrl,可以

function getUrl(model) {
   getFileUrl(model.id).then(url => model.url = url);
arr.forEach(getUrl);

最后,如果要等所有地址取完,除了上使用了 await 的 for ... of 之外,也可以使用 Promise.all 或 Promise.allSettled 来等待完成

(async () => {
    const promises = arr.map(async it => it.url = await getFileUrl(it.id));