VueJS中与GET请求的异步性

如何解决VueJS中与GET请求的异步性

我还是VueJS的新手。因此,我正在尝试向git API发出GET请求。首先,我提出了一个按照关注者数量对用户进行排序的请求,该请求以用户登录的降序检索出一个数组。之后,我对每个登录值都发出另一个GET请求,以获取更深入的数据,例如头像url,存储库计数等。问题是,而且我通常仍在处理异步问题,因为某些请求的执行速度比其他情况下,我的新对象数组在关注者数量方面变得混乱。我正在尝试执行sort()方法,但似乎无法弄清在js流中运行每个函数的顺序。有人可以帮我吗?

这是我正在使用的两个组件:

Home.vue

<template>
  <div>
    <div class="header">
      <h1>Devfinder</h1>
      <p>Find relevant developers from Github</p>
    </div>
    <div class="main">
      <SearchBars :fetchLogins="fetchLogins" />
      <CardList :cards="cards" />
    </div>
  </div>
</template>

<script>
import CardList from "./CardList";
import SearchBars from "./SearchBars";
import axios from "axios";

export default {
  name: "Home",data() {
    return {
      loginList: [],cardList: [],cards: [],page: 1,};
  },components: {
    SearchBars,CardList,},methods: {
    fetchLogins(language,location) {
      axios
        .get(
          `https://api.github.com/search/users?q=location:${location}+language:${language}&sort=followers&order=desc&page=${this.page}&per_page=8`,{
            headers: {
              Authorization: "***",}
        )
        .then((res) => {
          console.log(res.data);
          this.loginList = res.data.items.map((item) => item.login);
          console.log(this.loginList);
        })
        .catch((err) => console.log(err))
        .then(() => this.setCardInfo())
        .then(() => this.cards = this.cardList.sort((a,b) => b.followers - a.followers));
    },setCardInfo() {
      let newCardsArray = [];
      this.cards = [];
      this.cardList = [];
      // Zera o state de cards e itera o array loginList fazendo um GET request e criando o objeto para o array cards
      this.loginList.forEach((login) =>
        axios
          .get(`https://api.github.com/users/${login}`,})
          .then((res) => {
            const user = res.data;
            const cardObject = {
              id: user.id,name: user.name,avatar: user.avatar_url,bio: user.bio,followers: user.followers,repositories: user.public_repos,};
            newCardsArray.push(cardObject);
          })
      );
      // Por causa da assincronicidade,alguns objetos,mesmo com mais seguidores,acabam ficando atrás na ordem do array
      // invoco um sort() em ordem descendente
      this.cardList = newCardsArray;
    },};
</script>

和我的SearchBars组件


<template>
  <div>
    <form @submit="onSubmit">
      <p>Tech/Lang</p>
      <input type="text" v-model="language" placeholder="Type a technology or language" />
      <p>Location</p>
      <input type="text" v-model="location" placeholder="Type the desired location" />
      <input type="submit" value="FIND" />
    </form>
  </div>
</template>

<script>
export default {
  name: "SearchBars",data() {
      return {
          language: '',location: ''
      }
  },methods: {
      onSubmit(e){
          e.preventDefault();
          this.fetchLogins(this.language,this.location);
      }
  },props:["fetchLogins","getCardInfo"]
};
</script>

解决方法

之所以不起作用,是因为您的两个函数都不是异步的。对fetchLogins而言,这无关紧要,因为没有任何等待。但是,由于在fetchLogins中,您正在等待对setCardInfo的调用,因此需要setCardInfo是异步的。发生的是这一行:

.then(() => this.setCardInfo())

您的.then链会启动this.setCardInfo,但不会等到转移到链中的下一个.then之前。这是因为setCardInfo不会返回Promise,所以.then立即解决。


有两种方法可以做到这一点。您可以保持代码的当前组织方式,并使this.setCardInfo返回Promise;要么;您可以更改为async / await的语法(实际上是相同的),并使您的代码更具可读性。

定义async函数时,您真正要做的只是将其包装在return new Promise中,该函数的返回值是resolve的值。因此,这意味着您可以.then使用该功能。 但是,等一下!!当一个函数异步时,您可以使用特殊关键字await来告诉该函数“运行此行,等待其结束,然后继续前进” -实际上,您正在做的是.then-其余的功能,而不必链接另一个.then并添加另一个级别压痕。

在您的情况下,您可以使用的另一件事是Promise.all:您向它传递了一组Promises(据我们所知,async函数在幕后返回了!),并且只有在阵列中的所有功能都解决后,它才能解决承诺。因此,您可以做类似的事情,

async function myFunc(arr) {
  const responses = await Promise.all(arr.map(async item => {
    const res = await fetch('api',{ body: item });
    return await res.json();
  });
}

,最后得到的是arr项的响应的JSON数组。它所做的只是创建未解决的承诺数组,而Promise.all只是等待它们全部解决。如果其中任何一个拒绝,则Promise.all将拒绝。因此,当我在这里使用该范例时,我将其放在try中的catch / map中,因此希望您可以逐张处理它。 >

看看我提出的解决方案(这只是methods部分):

methods: {
    fetchLogins: async function(language,location) {
      let res;
      try {
        res = await axios.get(
          `https://api.github.com/search/users?q=location:${location}+language:${language}&sort=followers&order=desc&page=${this.page}&per_page=8`,{ headers: { Authorization: "90fa62d4dee8b02d363d83fccac86f3b7536492c" } }
        );
      } catch (err) {
        console.error(err);
        // deal w/ error,so the code below (dependent
        // on 'res') doesn't run. Or just let it err out.
        // up to you.
      }
      
      // None of this is async,so it doesn't need an await
      console.log(res.data);
      this.loginList = res.data.items.map(item => item.login);
      console.log(this.loginList);

      // Run the other function
      this.cards = [];
      this.cardList = [];

      // Keeping this as a separate function,since I don't know how you're
      // going to use it,but it could totally be be copied here.
      // "this.cardList // = await Promise.all ..." is really just one
      // line down there. Paste it here if you aren't gonna need it as a
      // separate function
      await this.setCardInfo();

      this.cards = this.cardList.sort((a,b) => b.followers = a.followers);
    },setCardInfo: async function () {
      this.cardList = await Promise.all(this.loginList.map(async login => {
        let res;
        try {
          res = axios.get(
            `https://api.github.com/users/${login}`,{ headers: { Authorization: "90fa62d4dee8b02d363d83fccac86f3b7536492c" } }
          );
        } catch (err) {
          console.errror(err);
          // Deal w/ error (return undefined? "couldn't find user's info"?)
        }

        const user = res.data;
        const cardObject = {
          id: user.id,name: user.name,avatar: user.avatar_url,bio: user.bio,followers: user.followers,respositories: user.public_repos
        };

        // Resolve the Promise for this iteration of the map funciton
        return cardObject;
      }));
    },},

我不是100%确信这对您有用,但是我认为我并未更改代码实际执行的任何操作,因此应该更改。如果没有,我希望对Promises和async / await的解释能成为踏脚石。

我建议您查看非常棒的MDN,以获取有关此资源的信息。他们甚至有一个starter guide您可以阅读,因此您不必简单地阅读正式文档。

,

尽量不要使用newCardsArray变量,只需将cardObject推入cardList即可。 在API调用完成之前,它正在分配空值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-