axios 从异步调用返回响应数据

vx6bjr1n  于 2022-11-05  发布在  iOS
关注(0)|答案(3)|浏览(318)

我创建了这个函数来从GDrive中获取我所有驱动器列表

async getAllDrives(token) {
        let nextPageToken = ""
        let resultArray = []        
        const config= {
            headers: {
                Authorization: `Bearer ${token}`
            }
        };
        const bodyParams = {            
            pageSize: 2,
            fields: 'nextPageToken, drives(id, name)',
            q:`hidden=false`,
        };
        do {
            axios.get(
                `https://www.googleapis.com/drive/v3/drives`,
                config,
                bodyParams,
            ).then(result => {
                nextPageToken = result.data.nextPageToken;  
                resultArray.push(result.data.drives);
                resultArray = resultArray.flat();                
                console.log("result", resultArray);
            }).catch(error => {
                console.log(error);
                //res.send(error);
            });
        }while(nextPageToken);
        resultArray = resultArray.flat();
        resultArray.map(drive => {
            drive.isSharedDrive = true;
        return drive;
        });
        return JSON.stringify(resultArray);

    }

查看console.log时

then(result => {
                nextPageToken = result.data.nextPageToken;  
                resultArray.push(result.data.drives);
                resultArray = resultArray.flat();                
                console.log("result", resultArray);

            })

我得到了预期的结果,

result [
  {
    kind: 'drive#drive',
    id: '**',
    name: ' ★ 🌩'
  },
]

但是return JSON.stringify(resultArray);是空的。我在这里发现了一个类似的问题,How do I return the response from an asynchronous call?,但是答案不令人满意。

ubof19bj

ubof19bj1#

您使用异步调用的方式有点不正确。您调用axios.get时没有使用await关键字,但使用了.then链接。因为您没有等待结果返回,所以您首先得到空数组,什么也没有返回。只有在此之后您在.then中的回调函数才被调用。为了简化,您在示例中这样做:

function getAllDrives() {
    // Local variable where you want your result
    let result = [];

    // You calling the axios.get method, but don't wait for result
    axios.get().then(result => {})

    // Empty result is getting returned immediately
    return result;
}

当远程服务器返回响应时,.then内部的函数试图将结果保存到本地变量中,但是函数已经完成,所以你什么也得不到。
实际上,您应该使用await关键字调用axios.get

// You should always cover your asynchronous code with a try/catch block
try {

    // Instead of `then` callback use `await` keyword. Promise returned from
    // this method will contain result. If error occurs, it will be thrown,
    // and you can catch it inside `catch`.
    const result = await axios.get(
        `https://www.googleapis.com/drive/v3/drives`,
        config,
        bodyParams
    );

    // Here is your code as you wrote it inside `then` callback
    nextPageToken = result.data.nextPageToken;
    resultArray.push(result.data.drives);
    resultArray = resultArray.flat();
    console.log("result", resultArray);

} catch (error) {

    // And here is your error handling code as you wrote it inside `catch`
    console.log(error);

}

这样,在请求未执行之前,您的方法不会完成。
你可以阅读更多关于async/await函数here的内容。

hec6srdp

hec6srdp2#

我相信你的目标如下。

  • 您希望使用axios检索驱动器列表。
  • 您的访问令牌可用于使用Drive API检索驱动器列表。

修改点:

  • 为了在请求中使用nextPageToken,在这种情况下,需要使用同步进程运行脚本。因此,使用async/await。这在现有的答案中已经提到。
  • 当我看到您的脚本时,我想查询参数可能需要包含在axios.get()的第二个参数中。
  • 为了使用nextPageToken,需要包含pageToken的属性。在您的脚本中,没有使用pageToken。这样,由于继续返回nextPageToken,因此会发生无限循环。

当这些要点反映在你的脚本中时,下面的修改怎么样?

修改的脚本:

let resultArray = [];
const config = {
  headers: {
    Authorization: `Bearer ${token}`,
  },
  params: {
    pageSize: 2,
    fields: "nextPageToken, drives(id, name)",
    q: `hidden=false`,
    pageToken: "",
  },
};
do {
  const { data } = await axios
    .get(`https://www.googleapis.com/drive/v3/drives`, config)
    .catch((error) => {
      if (error.response) {
        console.log(error.response.status);
        console.log(error.response.data);
      }
    });
  if (data.drives.length > 0) {
    resultArray = [...resultArray, ...data.drives];
  }
  nextPageToken = data.nextPageToken;
  config.params.pageToken = nextPageToken;
} while (nextPageToken);
resultArray.map((drive) => {
  drive.isSharedDrive = true;
  return drive;
});
return JSON.stringify(resultArray);

测试:

运行此脚本时,将获得以下结果。

[
  {"id":"###","name":"###","isSharedDrive":true},
  {"id":"###","name":"###","isSharedDrive":true},
  ,
  ,
  ,
]

注:

  • 来自官方文件“Drives:列表”,

pageSize:每页返回的最大共享驱动器数。可接受的值为1到100(包括1和100)。(默认值:10个)

  • 因此,当pageSize为100时,可以减少循环次数。如果要使用nextPageToken测试循环,请减少该值。

参考:

f87krz0w

f87krz0w3#

我建议您多学习一些关于async/await知识。
使用async并放置一个.then().catch()是没有意义的,async的目的是获得这些封装的语法。

async getAllDrives(token) {
  try {
    const getDrives = await this.request(token)
    console.log(getDrives)

    const results = this.resultArray(getDrives)
    return results
  } catch (e) {
    console.log(e)
  }
}

我不太明白你的想法和目标,要么让它适应你的代码,要么删除它

async request(token) {
  let nextPageToken = 1 // ????????
  const config = {
    headers: {
      Authorization: `Bearer ${token}`
    }
  };
  const bodyParams = {            
    pageSize: 2,
    fields: 'nextPageToken, drives(id, name)',
    q: `hidden=false`,
  };

  let getDrives = [];
  // loop for each request and create a request array
  for (let x = 0; x < fields.nextPageToken; x++) { 
    const request = axios.get(
      `https://www.googleapis.com/drive/v3/drives`,
      config,
      bodyParams
    );

    getDrives.push(request)
  }

  const drives = await Promise.all(getDrives)
  return drives
}

async resultArray(drivers) {
  // result treatment here
}

返回的promise all将是驱动程序响应的数组
注:www.example.com中的响应request.data

const request = await axios.get()
const resposta = request.data

阅读https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

相关问题