精华内容
下载资源
问答
  • 遇到这样一个需求:调用接口,返回一个新闻列表,再循环这个新闻列表,用每个新闻的id异步请求这个新闻的视频地址,这就需要在循环里调用接口。如果用for循环,接口还没请求完成,for循环就已经执行完了。所以改成...

    前言

    遇到这样一个需求:调用接口,返回一个新闻列表,再循环这个新闻列表,用每个新闻的id异步请求这个新闻的视频地址,这就需要在循环里调用接口。如果用for循环,接口还没请求完成,for循环就已经执行完了。所以改成promise去处理。

    开始

    整体思路就是:先存数组,然后循环生成每一个promise,然后用promise.all来调用,then的时候返回的是一个结果数组。

    1、首先定义循环里的异步请求

    getInfo(item ,index){
    			return new Promise((resolve,reject) => {
    				axios.post('/videoUrl',{id:item.id}).then(res=>{
    					let url = res.data;
    					resolve({id:item.id,url:url})
    				})
    			})
    		}
    

    2、newsList为开始接口获取的新闻列表,对新闻列表进行循环,得到一个promise数组。

    let promiseArr = this.newsList.map((item,index) => {
    				    return this.getInfo(item, index)
    				 })
    

    3、用promise.all来调。

    Promise.all(promiseArr).then(value=>{
    						console.log(value);
    					 //value:[{id: 1, url: "xxxxx"},
    					// 		  {id: 2, url: "xxxxx"},
    					// 		  {id: 3, url: "xxxxx"}]
    						this.newsList = value;
    					})
    

    这样就拿到了包含新闻视频地址的新闻列表。

    全部代码

    <script>
    export default {
    	name: 'empty',
    	data () {
    		return {
    			newsList:[]//新闻列表
    		}
    	},
    	methods:{
    			getNewsList(){
    				axios.get('/newsList').then(res=>{
    					this.newsList = res.data;//newsList = [{id:1},{id:2},{id:3}];
    					let promiseArr = this.newsList.map((item,index) => {
    						return this.getInfo(item, index)
    					})
    					Promise.all(promiseArr).then(value=>{
    						console.log(value);
    					 //value:[{id: 1, url: "xxxxx"},
    					// 		  {id: 2, url: "xxxxx"},
    					// 		  {id: 3, url: "xxxxx"}]
    						this.newsList = value;
    					})
    				})
    			},
    			// 通过新闻id请求新闻视频地址
    			getInfo(item ,index){
    				return new Promise((resolve,reject) => {
    					axios.post('/videoUrl',{id:item.id}).then(res=>{
    						let url = res.data;
    						resolve({id:item.id,url:url})
    					})
    				})
    			}
    	},
    	mounted(){
    		this.getNewsList();
    	}
    }
    </script>
    

    后记

    1、首先关于后台修改接口,正常返回应该是newsList里就返回了视频地址,协商过就是需要单独去调用。
    2、这个问题的解决花费了时间,特此记录。文章参考javascript for循环+异步请求导致请求顺序不一致

    展开全文
  • 1、问题背景问题:当查询接口较复杂时候,数据的获取都需要远程调用,必然需要花费更多的时间。假如查询文章详情页面,需要如下标注的时间才能完成:那么,用户需要4s后才能统计的数据。很显然是不能接受的。如果有...

    c685958a65d31b6594cf2a6da68d40d7.png

    1、问题背景

    问题:当查询接口较复杂时候,数据的获取都需要远程调用,必然需要花费更多的时间。

    假如查询文章详情页面,需要如下标注的时间才能完成:

    ddf7635e1c8785b1932b30b4cfc4dcc5.png

    那么,用户需要4s后才能统计的数据。很显然是不能接受的。

    如果有多个线程同时完成这4步操作,也许只需要1s左右即可完成响应。

    2、CompletableFuture介绍

    在Java 8中, 新增加了一个包含50个方法左右的类: CompletableFuture,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。

    CompletableFuture类实现了Future接口,所以你还是可以像以前一样通过get方法阻塞或者轮询的方式获得结果,但是这种方式不推荐使用。

    CompletableFuture和FutureTask同属于Future接口的实现类,都可以获取线程的执行结果。

    276af4a49c6aa65e80e8001c55ec66b0.png
    2.1 创建异步对象

    CompletableFuture 提供了四个静态方法来创建一个异步操作。

    a9a5c0bafc11adc2088251ac7750680b.png

    没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

    runAsync方法不支持返回值。supplyAsync可以支持返回值。

    2.2 计算完成时回调方法

    当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法:

    46bc9b41e8ccbd5b411aced9055c756b.png

    whenComplete可以处理正常和异常的计算结果,exceptionally处理异常情况。BiConsumer super T,? super Throwable>可以定义处理业务

    whenComplete 和 whenCompleteAsync 的区别:

    whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

    方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)

    2.3 线程串行化方法

    thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。

    thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。

    thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作

    带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。

    5025c5e52a586be573510cf0f20b4e30.png

    Function super T,? extends U>

    T:上一个任务返回结果的类型

    U:当前任务的返回值类型

    2.4 多任务组合

    7f60fe416d6e9824498fa02c077ca36a.png

    allOf:等待所有任务完成

    anyOf:只要有一个任务完成

    3、例子

    b9088691b7a715ff18ece973fcd6f389.png

    11c6c7efe1b442273c142e0ec8d1508a.png

    上面例子完美呈现,计算完成时回调方法CompletableFuture.supplyAsync()、线程串行化方法articleCompletableFuture.thenAcceptAsync()、创建异步对象CompletableFuture.runAsync()、多任务组合CompletableFuture.allOf()

    展开全文
  • 这种方式主要应用于提供者接口响应耗时明显,消费者端可以利用调用接口的时间去做一些其他的接口调用,利用 Future 模式来异步等待和获取结果即可。 这种方式可以大大的提升消费者端的利用率。 目前这种方式可以通过...

    dubbo学习笔记—dubbo中的异步调用

    1. 异步调用

    1. Dubbo不只提供了堵塞式的的同步调用,同时提供了异步调用的方式。这种方式主要应用于提供者接口响应耗时明显,消费者端可以利用调用接口的时间去做一些其他的接口调用,利用 Future 模式来异步等待和获取结果即可。
    2. 这种方式可以大大的提升消费者端的利用率。 目前这种方式可以通过XML的方式进行引入。

    2. 异步调用的实现

    1. 为了能够模拟等待,通过 int timeToWait参数,标明需要休眠多少毫秒后才会进行返回。

      String sayHello(String name, int timeToWait);
      
    2. 接口实现为了模拟调用耗时 可以让线程等待一段时间

    3. 在消费者端,配置异步调用 注意消费端默认超时时间1000毫秒 如果提供端耗时大于1000毫秒会出现超时,可以通过改变消费端的超时时间 通过timeout属性设置即可单位毫秒

      <dubbo:reference id="helloService" interface="com.lagou.service.HelloService"> 
      		<dubbo:method name="sayHello" async="true" /> 
      </dubbo:reference>
      
    4. 测试,我们休眠100毫秒,然后再去进行获取结果。方法在同步调用时的返回值是空,我们可以通过RpcContext.getContext().getFuture() 来进行获取Future对象来进行后续的结果等待操作。

    3. 异步调用的特殊说明

    1. 需要特别说明的是,该方式的使用,请确保dubbo的版本在2.5.4及以后的版本使用。
    2. 原因在于在2.5.3及之前的版本使用的时候,会出现异步状态传递问题。
    3. 比如我们的服务调用关系是 A -> B -> C , 这时候如果A向B发起了异步请求,在错误的版本时,B向C发起的请求也会连带的产生异步请求。
    4. 这是因为在底层实现层面,他是通过 RPCContext 中的attachment 实现的。在A向B发起异步请求时,会在 attachment 中增加一个异步标示字段来表明异步等待结果。
    5. B在接受到A中的请求时,会通过该字段来判断是否是异步处理。但是由于值传递问题,B向 C发起时同样会将该值进行传递,导致C误以为需要异步结果,导致返回空。
    6. 这个问题在2.5.4及以后的版本进行了修正。
    7. 修正链接:https://github.com/apache/dubbo/blob/47ee52d122fb6f0462ed99530cfe462c591feac8/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java#L70-L71
    展开全文
  • dubbo-8:异步调用

    2020-12-20 16:21:25
    待和获取结果即可。这种方式可以大大的提升消费者端的利用率。 目前这种方式可以通过XML的方式进 行引入。 1、模拟等待 为了能够模拟等待,通过 int timeToWait参数,标明需要休眠多少毫秒后才会进行返回。 public ...

    官方说明
    Dubbo不只提供了堵塞式的的同步调用,同时提供了异步调用的方式。这种方式主要应用于提供者接口
    响应耗时明显,消费者端可以利用调用接口的时间去做一些其他的接口调用,利用 Future 模式来异步等
    待和获取结果即可。这种方式可以大大的提升消费者端的利用率。 目前这种方式可以通过XML的方式进
    行引入。

    1、模拟等待

    为了能够模拟等待,通过 int timeToWait参数,标明需要休眠多少毫秒后才会进行返回。

    public interface HelloService {
        String sayHello(String name, int timeToWait);
    }
    

    2、接口实现

    为了模拟调用耗时 可以让线程等待一段时间

    public class HelloServiceImpl implements HelloService {
        public String sayHello(String name, int timeToWait) {
            try {
                Thread.sleep(timeToWait);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello1111:"+name;
        }
    }
    

    3、消费者端

    配置异步调用
    注意消费端默认超时时间1000毫秒 如果提供端耗时大于1000毫秒会出现超时。可以通过改变消费端的超时时间 通过timeout属性设置即可单位毫秒

      <dubbo:method name="sayHello" async="true"/>
    

    完整如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://dubbo.apache.org/schema/dubbo
           http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
        <dubbo:application name="service-consumer" >
            <dubbo:parameter key="qos.enable" value="true" ></dubbo:parameter>
            <dubbo:parameter key="qos.port" value="33333"></dubbo:parameter>
            <!-- value为true:talnet用ip登录之后可以操作,否则只能登录不能操作-->
            <dubbo:parameter key="qos.accept.foreign.ip" value="true" ></dubbo:parameter>
    
        </dubbo:application>
    
        <!-- 使用multicast广播注册中心暴露发现服务地址 -->
        <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    
        <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
        <dubbo:reference id="helloService" interface="com.lagou.service.HelloService" >
            <!-- 设置方法是否异步调用 :默认是false。
            TODO 注意:方法在异步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture()
                     获取Future对象,来进行后续的结果等操作
            -->
            <dubbo:method name="sayHello" async="true"/>
        </dubbo:reference>
    </beans>
    

    4、测试

    我们休眠100毫秒,然后再去进行获取结果。方法在同步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture() 来进行获取Future对象来进行后续的结果等待操作。

    package com.lagou;
    
    import com.lagou.service.HelloService;
    import org.apache.dubbo.rpc.RpcContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.io.IOException;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    
    public class XMLConsumerMain {
        public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-comsumer.xml");
            System.out.println("Consumer 启动成功!");
            HelloService helloService = (HelloService) context.getBean("helloService");
            System.out.println("获取接口成功!");
    
            while (true) {
                System.in.read();
    
                String result = helloService.sayHello("haha哈喽", 100);
                // 利用Future 模式来获取
                Future<Object> future = RpcContext.getContext().getFuture();
                System.out.println("result:" + result);
                System.out.println("future===》result:" + future.get());
            }
        }
    }
    
    

    5、注意

    方法在异步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture() 获取Future对象,来进行后续的结果等操作。详见第4步测试类中的具体代码
    在这里插入图片描述

    展开全文
  • 利用Future异步获取多线程的返回结果

    万次阅读 多人点赞 2016-08-29 12:11:05
    Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步...在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否
  • Future是Java 5添加的类,用来描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种...
  • Future是Java 5添加的类,用来描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种...
  • 文章目录1. Tips:什么是Future类型?2. 正常用future的get(long timeout, ...Future是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果接口。必要时可以通过get方法获取执行结...
  • Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来...在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结...
  • 通过线程池的submit方法和实现了callable接口的对象,可以返回一个future接口的对象,通过此对象可以异步获取callable方法的运行结果。 future.get() 阻塞式的返回结果,如果任务未执行完毕,就阻塞等待结果产生。 ...
  • 当UI动作引发一个耗时的计算时,我们经常需要将这个耗时的过程放到后台线程中去完成,然后获取该过程的结果。使用.NET提供的默认设施,无论是... AsynCaller通过事件来通知外部异步调用结果,IAsynCaller接口如下...
  • vue调用接口同步实现

    2021-02-25 11:40:37
    实现字典项数据后端获取,始终无法同步返回结果,在网上找了好多vue同步接口的方法,都是说在方法前加async,在接口名前加await,自己试了好长时间也不好使,最终只能选择用回调函数的方法来达到方法的同步调用,回...
  • 我想在created里获取到这两个结果,存在storage里在beforeMount里调用,可是不能行之前我是直接用new Promise一路then下来,最后一个then里调用轮播方法传进去openId和token,想问下还有别的方...
  • //获取项目名 function sysName(){ var pathName = window.document.location.pathname; var projectName = pathName.substring(0,pathName.substr(1).indexOf('/')+1); return (projectName); }
  • 背景: 在我们日常的开发中,很多时候我们的接口会有比较复杂的...比如有这样的场景,我们需要去调用三个第三方的api获取结果后并且相加,每个api大概需要花2s 代码: public int getA(){ try { Thread.sleep(2000);
  • 第4章 接口调用方式

    2020-11-17 12:11:16
    第4章 接口调用方式 接口调用方式 ...得到异步任务正确的结果 .catch() 获取异常信息 .finally() 成功与否都会执行(不是正式标准) 静态方法 .all() Promise.all 方法接受一个数组作参数,数组中的对象
  • 再次强调ajax和jsonp是两个概念,但是由于jquery的封装,使这两种异步接口调用方式,看起来比较相近,但在底层差别还是比较大的(本文只写服务端的实现)。  为了便于讲解我使用express框架来运行我的demo。并...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 276
精华内容 110
关键字:

异步调用接口获取结果