精华内容
下载资源
问答
  • 2.如何让他们并行执行,然后三个请求都执行完成后,再执行某个操作? 我觉得写三个$.ajax不就是并发执行了吗,然后遍历看是否都返回结果了,如果都返回结果了,再进行继续的操作,这么想对吗? 意义是什么呢? 经过...

    昨天面试的时候看到的一个题

    1.有三个ajax请求,如何让这三个ajax请求串行执行,即第一个执行完成后在执行另一个?
    我回答的是判断上一个请求返回结果,执行完成之后在执行下一个,对吗?
    2.如何让他们并行执行,然后三个请求都执行完成后,再执行某个操作?

    我觉得写三个$.ajax不就是并发执行了吗,然后遍历看是否都返回结果了,如果都返回结果了,再进行继续的操作,这么想对吗?

    意义是什么呢?

    经过csdn的大神的解答明白了,其实考察的就是同步和异步。

    //串行执行分两种。一是用同步模式async: false,三个ajax请求连着写就可以了。
    $.ajax({
        url: "ajax请求1",
        async: false,
        success: function (data) {
            console.log("ajax请求1 完成");
        }
    });
    $.ajax({
        url: "ajax请求2",
        async: false,
        success: function (data) {
            console.log("ajax请求2 完成");
        }
    });
    $.ajax({
        url: "ajax请求3",
        async: false,
        success: function (data) {
            console.log("ajax请求2 完成");
        }
    });
     
    //二是用异步模式async: true,三个ajax请求嵌套写。
    $.ajax({
        url: "ajax请求1",
        async: true,
        success: function (data) {
            console.log("ajax请求1 完成");
            $.ajax({
                url: "ajax请求2",
                async: true,
                success: function (data) {
                    console.log("ajax请求2 完成");
                    $.ajax({
                        url: "ajax请求3",
                        async: true,
                        success: function (data) {
                            console.log("ajax请求3 完成");
                        }
                    });
                }
            });
        }
    });
     
     
    //并行执行就只能用异步模式。并设置变量进行计数
    var num = 0;
    function isAllSuccess() {
        num++;
        if (num>=3)
            console.log("三个ajax请求全部完成");
    }
    $.ajax({
        url: "ajax请求1",
        async: true,
        success: function (data) {
            console.log("ajax请求1 完成");
            isAllSuccess();
        }
    });
    $.ajax({
        url: "ajax请求2",
        async: true,
        success: function (data) {
            console.log("ajax请求3 完成");
            isAllSuccess();
        }
    });
    $.ajax({
        url: "ajax请求3",
        async: true,
        success: function (data) {
            console.log("ajax请求3 完成");
            isAllSuccess();
        }
    });
    
    展开全文
  • ajax请求串行和并行的问题

    千次阅读 2017-05-30 23:48:57
    2.如何让他们并行执行,然后三个请求都执行完成后,再执行某个操作? //串行执行分两种。 //一是用同步模式async: false,三个ajax请求连着写就可以了。 $.ajax({ url: "ajax请求1", async: false,

    两个问题:

    1.有三个ajax请求,如何让这三个ajax请求串行执行,即第一个执行完成后在执行另一个?

    2.如何让他们并行执行,然后三个请求都执行完成后,再执行某个操作?

    //串行执行分两种。  
    //一是用同步模式async: false,三个ajax请求连着写就可以了。  
    $.ajax({  
        url: "ajax请求1",  
        async: false,  
        success: function (data) {  
            console.log("ajax请求1 完成");  
        }  
    });  
    $.ajax({  
        url: "ajax请求2",  
        async: false,  
        success: function (data) {  
            console.log("ajax请求2 完成");  
        }  
    });  
    $.ajax({  
        url: "ajax请求3",  
        async: false,  
        success: function (data) {  
            console.log("ajax请求2 完成");  
        }  
    });  
       
    //二是用异步模式async: true,三个ajax请求嵌套写。  
    $.ajax({  
        url: "ajax请求1",  
        async: true,  
        success: function (data) {  
            console.log("ajax请求1 完成");  
            $.ajax({  
                url: "ajax请求2",  
                async: true,  
                success: function (data) {  
                    console.log("ajax请求2 完成");  
                    $.ajax({  
                        url: "ajax请求3",  
                        async: true,  
                        success: function (data) {  
                            console.log("ajax请求3 完成");  
                        }  
                    });  
                }  
            });  
        }  
    });  
       
       
    //并行执行就只能用异步模式。并设置变量进行计数  
    var num = 0;  
    function isAllSuccess() {  
        num++;  
        if (num>=3)  
            console.log("三个ajax请求全部完成");  
    }  
    $.ajax({  
        url: "ajax请求1",  
        async: true,  
        success: function (data) {  
            console.log("ajax请求1 完成");  
            isAllSuccess();  
        }  
    });  
    $.ajax({  
        url: "ajax请求2",  
        async: true,  
        success: function (data) {  
            console.log("ajax请求3 完成");  
            isAllSuccess();  
        }  
    });  
    $.ajax({  
        url: "ajax请求3",  
        async: true,  
        success: function (data) {  
            console.log("ajax请求3 完成");  
            isAllSuccess();  
        }  
    });


    目前ES6中Promise可以用.then链也可以实现多层异步回调的问题,ES7中的Async和Await解决了.then链复杂的写法。await是等待一个Promise对象或者一个表达式的值;如果await等待的是一个Promise对象,那么就会阻塞后面的代码来等待Promise对象resolve,等resolve完成将resolve结果返回实现回调;这样的话,用一个aync和多个await就可以轻松的完成多层嵌套异步回调,且写法优雅,代码简单。

    我的Github上有案例源码:https://github.com/spicyboiledfish/JavaScript-testJS/blob/master/53.全面理解ES6中的Promise.html

    具体详解请查看下面两篇博客:

    ES6中的Promise: http://www.cnblogs.com/lvdabao/p/es6-promise-1.html

    ES7中的async和await:http://blog.csdn.net/hj7jay/article/details/61191416


    展开全文
  • *前言:最近写的app需要综合用到api的串行和并行, 所以整理了下使用的api的情况。 主要用到的GCD方法:dispatch_group_leave, dispatch_group_enter, 以及semaphore的运用。* 1. 信号量串行顺序请求。...

    其他链接:
    - Qt学习笔记之–多线程
    - Python学习笔记之–多线程和多进程





    前言:最近写的app需要综合用到api的串行和并行, 所以整理了下使用的api的情况。
    主要用到的GCD方法:dispatch_group_leavedispatch_group_enter, 以及semaphore的运用。


    1. 信号量串行顺序请求。(semaphore)

    code:

     - (void)test {
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        
        NSLog(@"请求开始");
        dispatch_group_async(group, queue, ^{
            for (int i = 0; i < 4; i++) {
                NSLog(@"----------开始请求 i = %i", i);
                //随便请求都行
                [BYNetPort requestFileSettingsSuccess:^(id responseObject) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_semaphore_signal(semaphore);
                } failure:^(NSError *error) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_semaphore_signal(semaphore);
                }];
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            }
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"----全部请求完毕---");
        });
    }
    

    以下是输出结果:

    2018-09-07 15:37:46.567017+0800 kantan[32591:12521747] 请求开始
    2018-09-07 15:37:46.567213+0800 kantan[32591:12521836] ----------开始请求 i = 0
    2018-09-07 15:37:47.123672+0800 kantan[32591:12521747] --------成功 i = 0
    2018-09-07 15:37:47.123853+0800 kantan[32591:12521836] ----------开始请求 i = 1
    2018-09-07 15:37:47.622304+0800 kantan[32591:12521747] --------成功 i = 1
    2018-09-07 15:37:47.622575+0800 kantan[32591:12521836] ----------开始请求 i = 2
    2018-09-07 15:37:48.648025+0800 kantan[32591:12521747] --------成功 i = 2
    2018-09-07 15:37:48.648289+0800 kantan[32591:12521836] ----------开始请求 i = 3
    2018-09-07 15:37:49.216007+0800 kantan[32591:12521747] --------成功 i = 3
    2018-09-07 15:37:49.216195+0800 kantan[32591:12521836] ----全部请求完毕---
    

    小结: 使用信号量由三组函数构成: dispatch_semaphore_createdispatch_semaphore_signaldispatch_semaphore_wait。注意当dispatch_semaphore_create函数的值传为0的时候,为串行顺序的执行, 当值 >0 的时候,为并行队列,但是需要配合第二节 enterleave使用, 不然会当数据还未请求完成时,便进入dispatch_group_notify方法。

    比如将dispatch_semaphore_create的参数变为 2, 会出现以下打印结果。注意会当数据还未请求完成时,便进入dispatch_group_notify方法

    2018-09-07 15:50:08.531976+0800 kantan[32903:12533391] 请求开始
    2018-09-07 15:50:08.532385+0800 kantan[32903:12533484] ----------开始请求 i = 0
    2018-09-07 15:50:08.543797+0800 kantan[32903:12533484] ----------开始请求 i = 1
    2018-09-07 15:50:08.548670+0800 kantan[32903:12533484] ----------开始请求 i = 2
    2018-09-07 15:50:09.111805+0800 kantan[32903:12533391] --------成功 i = 1
    2018-09-07 15:50:09.112008+0800 kantan[32903:12533484] ----------开始请求 i = 3
    2018-09-07 15:50:09.112148+0800 kantan[32903:12533391] --------成功 i = 2
    2018-09-07 15:50:09.113628+0800 kantan[32903:12533391] --------成功 i = 0
    2018-09-07 15:50:09.113659+0800 kantan[32903:12533484] ----全部请求完毕---
    2018-09-07 15:50:09.646332+0800 kantan[32903:12533391] --------成功 i = 3
    

    2.并行请求 group leave 和 enter

    code:

    - (void)test {
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        NSLog(@"请求开始");
        dispatch_group_async(group, queue, ^{
            for (int i = 0; i < 4; i++) {
                NSLog(@"----------开始请求 i = %i", i);
                //随便请求都行
                [BYNetPort requestFileSettingsSuccess:^(id responseObject) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_group_leave(group);
                } failure:^(NSError *error) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_group_leave(group);
                }];
                dispatch_group_enter(group);
            }
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"----全部请求完毕---");
        });
    }
    

    以下是输出结果:

    2018-09-07 15:43:24.538455+0800 kantan[32746:12527236] 请求开始
    2018-09-07 15:43:24.538653+0800 kantan[32746:12527354] ----------开始请求 i = 0
    2018-09-07 15:43:24.548369+0800 kantan[32746:12527354] ----------开始请求 i = 1
    2018-09-07 15:43:24.549534+0800 kantan[32746:12527354] ----------开始请求 i = 2
    2018-09-07 15:43:24.550806+0800 kantan[32746:12527354] ----------开始请求 i = 3
    2018-09-07 15:43:25.064171+0800 kantan[32746:12527236] --------成功 i = 0
    2018-09-07 15:43:25.145752+0800 kantan[32746:12527236] --------成功 i = 2
    2018-09-07 15:43:25.146124+0800 kantan[32746:12527236] --------成功 i = 1
    2018-09-07 15:43:25.155443+0800 kantan[32746:12527236] --------成功 i = 3
    2018-09-07 15:43:25.155616+0800 kantan[32746:12527348] ----全部请求完毕---
    

    **小结:**单纯使用dispatch_group_enterdispatch_group_leave 控制并行队列。 虽然可以在所有队列请求结束后进入dispatch_group_notify方法。 但是还有个问题是 不能控制同时并发数,如果for循环的i为1000, 那么会并行1000个线程。 如果对并行线程数没有要求的可以考虑此方法。


    3. group和信号量混合使用,控制同时并发数

    code:

    - (void)test {
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
        
        NSLog(@"请求开始");
        dispatch_group_async(group, queue, ^{
            for (int i = 0; i < 6; i++) {
                NSLog(@"----------开始请求 i = %i", i);
                //随便请求都行
                [BYNetPort requestFileSettingsSuccess:^(id responseObject) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_group_leave(group);
                    dispatch_semaphore_signal(semaphore);
                } failure:^(NSError *error) {
                    NSLog(@"--------成功 i = %i",i);
                    dispatch_group_leave(group);
                    dispatch_semaphore_signal(semaphore);
                }];
                dispatch_group_enter(group);
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            }
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"----全部请求完毕---");
        });
    }
    

    以下是输出结果:

    2018-09-07 15:56:58.368120+0800 kantan[33065:12539726] 请求开始
    2018-09-07 15:56:58.368321+0800 kantan[33065:12539783] ----------开始请求 i = 0
    2018-09-07 15:56:58.392233+0800 kantan[33065:12539783] ----------开始请求 i = 1
    2018-09-07 15:56:58.394367+0800 kantan[33065:12539783] ----------开始请求 i = 2
    2018-09-07 15:56:58.912951+0800 kantan[33065:12539726] --------成功 i = 0
    2018-09-07 15:56:58.915470+0800 kantan[33065:12539783] ----------开始请求 i = 3
    2018-09-07 15:56:58.957665+0800 kantan[33065:12539726] --------成功 i = 2
    2018-09-07 15:56:58.957837+0800 kantan[33065:12539783] ----------开始请求 i = 4
    2018-09-07 15:56:58.979873+0800 kantan[33065:12539726] --------成功 i = 1
    2018-09-07 15:56:58.980089+0800 kantan[33065:12539783] ----------开始请求 i = 5
    2018-09-07 15:56:59.418535+0800 kantan[33065:12539726] --------成功 i = 3
    2018-09-07 15:56:59.480643+0800 kantan[33065:12539726] --------成功 i = 4
    2018-09-07 15:56:59.495432+0800 kantan[33065:12539726] --------成功 i = 5
    2018-09-07 15:56:59.495599+0800 kantan[33065:12539786] ----全部请求完毕---
    

    小结: 注意信号量的初始值传的是2. 所以我们最多同开辟3个串行队列。
    两者的混合使用,完美的解决了控制并发数量,并监听 所有的请求结束。

    展开全文
  • 现在有这么个逻辑需求, 并行请求两个网络请求 AB , 但是要确保先处理A的结果, 在处理B的结果.实现这个需求其实很简单, 只要定义一个全局变量去判断就可以了, 或者利用挂起线程等等操作, 我们这里使用Rxjava的操作...

    现在有这么个逻辑需求, 并行请求两个网络请求 A和B , 但是要确保先处理A的结果, 在处理B的结果.

    实现这个需求其实很简单, 只要定义一个全局变量去判断就可以了, 或者利用挂起线程等等操作, 我们这里使用Rxjava的操作符来实现一下.

    先看一下A方案

    public static ObservableTransformer rxSchedulerHelper() { //compose简化线程

    return new ObservableTransformer() {

    @Override

    public ObservableSource apply(Observable observable) {

    return observable.subscribeOn(Schedulers.io())

    .observeOn(AndroidSchedulers.mainThread());

    }

    };

    }

    Observable a; // A请求

    a.compose(RxUtil.rxSchedulerHelper());

    Observable b; // B请求

    b.compose(RxUtil.rxSchedulerHelper());

    Observable.zip(a, b, new BiFunction(){

    @Override

    public Object apply(@NonNull String s, @NonNull Integer integer) throws Exception {

    // dosomething with A结果

    // dosomething with B结果

    return new Object();

    }

    }).subscribe();

    看完这个A方案, A和B会并行在各自的子线程当中, 并且会合并到 apply()方法中.

    这里可以先处理A的处理结果s, 后处理B的处理结果integer.

    弊端: 效率低

    根据上面的写法apply()方法, 必然是两个请求结果都收到之后才会调用的方法. 如果A请求先结束, 那么完全可以先处理A的请求结果, 而不去等待B的请求结果

    B方案, 提高效率

    Observable a; // A请求

    a.compose(RxUtil.rxSchedulerHelper());

    a.doOnEach(new Consumer>() {

    @Override

    public void accept(@NonNull Notification stringNotification) throws Exception {

    //do something with A结果

    }

    });

    Observable b; // B请求

    b.compose(RxUtil.rxSchedulerHelper());

    Observable.zip(a, b, new BiFunction(){

    @Override

    public Object apply(@NonNull String s, @NonNull Integer integer) throws Exception {

    // dosomething with B结果

    return new Object();

    }

    }).subscribe();

    如果A优先请求结束, 那么会执行 doOnEach() 中的方法, 接着在执行 apply() 中的方法.

    如果B优先请求结束, 也是相同的结果.

    弊端: 没有考虑到两个请求出错的情况.

    如果B请求时出错, 但是这是A请求还没有完成, 那么A的请求就会被中断, 但是我的业务逻辑是A请求不应该不受到B请求的影响, 也就是说B请求就算出错了, A请求也需要继续请求, 并处理结果.

    为了实现这个需求我们需要用到 zip() 操作符中的 delayError 功能

    也就是延迟报错. 我们先看一下 zip() 的源码, 看看 delayError 是如何工作的

    // Observable

    public static Observable zipArray(Function super Object[], ? extends R> zipper,

    boolean delayError, int bufferSize, ObservableSource extends T>... sources) {

    //...

    return RxJavaPlugins.onAssembly(new ObservableZip(sources, null, zipper, bufferSize, delayError));

    }

    // ObservableZip

    public ObservableZip(ObservableSource extends T>[] sources,

    Iterable extends ObservableSource extends T>> sourcesIterable,

    Function super Object[], ? extends R> zipper,

    int bufferSize,

    boolean delayError) {

    this.sources = sources; // 请求A, B 的数组

    this.sourcesIterable = sourcesIterable; // null

    this.zipper = zipper; // apply() 方法

    this.bufferSize = bufferSize; // 因为数据量小, 这个可以忽略

    this.delayError = delayError; // 是否延迟加载

    }

    public void subscribeActual(Observer super R> s) {

    ObservableSource extends T>[] sources = this.sources;

    int count = 0;

    if (sources == null) {

    // source 不为空

    } else {

    count = sources.length;

    }

    ZipCoordinator zc = new ZipCoordinator(s, zipper, count, delayError);

    zc.subscribe(sources, bufferSize);

    }

    ZipCoordinator(Observer super R> actual,

    Function super Object[], ? extends R> zipper,

    int count, boolean delayError) {

    // 观察者

    this.actual = actual;

    // 转换方法

    this.zipper = zipper;

    // 包装观察者数组

    this.observers = new ZipObserver[count];

    // 每个被观察者产生数据后保存在该数组

    this.row = (T[])new Object[count];

    // 如果上面的容器中有数据时, 延迟发送error

    this.delayError = delayError;

    }

    public void subscribe(ObservableSource extends T>[] sources, int bufferSize) {

    // 给 包装观察者数组元素赋值

    ZipObserver[] s = observers;

    int len = s.length;

    for (int i = 0; i < len; i++) {

    s[i] = new ZipObserver(this, bufferSize);

    }

    this.lazySet(0);

    actual.onSubscribe(this);

    for (int i = 0; i < len; i++) {

    if (cancelled) {

    return;

    }

    // 订阅 被观察者

    // 这里研究被观察者为异步时的情况

    sources[i].subscribe(s[i]);

    }

    }

    // 包装后的观察者

    ZipObserver(ZipCoordinator parent, int bufferSize) {

    // 上面的ZipCoordinator

    this.parent = parent;

    // 队列, 存储 被观察者发送的数据

    this.queue = new SpscLinkedArrayQueue(bufferSize);

    }

    @Override

    public void onNext(T t) {

    // 队列添加元素

    queue.offer(t);

    parent.drain();

    }

    @Override

    public void onError(Throwable t) {

    error = t;

    // done为true 说明结束事件

    done = true;

    parent.drain();

    }

    @Override

    public void onComplete() {

    done = true;

    parent.drain();

    }

    // 先简单看一下取消事件的方法

    void clear() {

    for (ZipObserver, ?> zs : observers) {

    // 清空每个包装观察者的队列

    zs.queue.clear();

    }

    }

    // 取消方法

    void cancel() {

    clear();

    cancelSources();

    }

    void cancelSources() {

    for (ZipObserver, ?> zs : observers) {

    // 调用dispose() 终止事件

    zs.dispose();

    }

    }

    上面事件中 都调用了 parent.drain()方法

    public void drain() {

    if (getAndIncrement() != 0) {

    return;

    }

    int missing = 1;

    final ZipObserver[] zs = observers;

    final Observer super R> a = actual;

    final T[] os = row;

    final boolean delayError = this.delayError;

    for (;;) {

    for (;;) {

    int i = 0;

    int emptyCount = 0;

    for (ZipObserver z : zs) {

    if (os[i] == null) {

    // 观察者是否结束

    boolean d = z.done;

    // 从观察者队列中取出元素

    T v = z.queue.poll();

    // 刚刚取出的元素是否为空

    boolean empty = v == null;

    // 如果 d = true 并且 队列中没有元素, 那么必然为true

    // 如果 d = true 并且 队列中有元素, 延迟发送Error, 那么为false

    // 只要 d = true 那么 return 后不是cancel, 就是 onComplete

    if (checkTerminated(d, empty, a, delayError, z)) {

    return;

    }

    if (!empty) {

    // 不为空 数组添加数据

    os[i] = v;

    } else {

    emptyCount++;

    }

    } else {

    // 当 os容器中有数据并且不延迟发送Error 并且 error不为空, 终止事件

    if (z.done && !delayError) {

    Throwable ex = z.error;

    if (ex != null) {

    cancel();

    a.onError(ex);

    return;

    }

    }

    }

    i++;

    }

    // emptyCount 不等于0表示有个观察者中的队列还没有数据

    // 如果要执行下面的 onNext() 必须要所有观察者都提供数据才能接着执行下去

    if (emptyCount != 0) {

    break;

    }

    R v;

    try {

    v = ObjectHelper.requireNonNull(zipper.apply(os.clone()), "The zipper returned a null value");

    } catch (Throwable ex) {

    Exceptions.throwIfFatal(ex);

    cancel();

    a.onError(ex);

    return;

    }

    a.onNext(v);

    Arrays.fill(os, null);

    }

    missing = addAndGet(-missing);

    if (missing == 0) {

    return;

    }

    }

    }

    boolean checkTerminated(boolean d, boolean empty, Observer super R> a, boolean delayError, ZipObserver, ?> source) {

    // 判断是否结束

    if (cancelled) {

    cancel();

    return true;

    }

    // d 是观察者的 done

    if (d) {

    // 如果是延迟发送Error

    if (delayError) {

    // 如果队列取出的元素为空

    if (empty) {

    Throwable e = source.error;

    // 取消事件

    cancel();

    if (e != null) {

    a.onError(e);

    } else {

    a.onComplete();

    }

    return true;

    }

    // 结论: 如果延迟发送Error并且队列中有数据, 就不会取消事件

    } else {

    // 不延迟发送消息

    Throwable e = source.error;

    if (e != null) {

    cancel();

    a.onError(e);

    return true;

    } else

    if (empty) {

    cancel();

    a.onComplete();

    return true;

    }

    // 结论: 不延迟发送Error时, 如果有 error或者队列为空 都会取消事件

    }

    }

    return false;

    }

    根据 drain() 方法可以知道, 想要延迟报错, 那么 delayError 为true是必须的. 并且观察者队列中的数据不能为空. 这样就算出错了, 他也会继续执行.

    方案B中如果B请求出错了, 它的观察者队列中没有数据, 所以会直接取消所有事件

    根据这个点出发实现方案C

    // 不放实例代码了, 直接贴项目中使用的代码

    public static ObservableTransformer concurrentRequestOrderRespond(

    final Observable source2

    , final Consumer onNext

    , final Consumer onError

    , final Action onComplete

    , final Consumer source2Exc){

    return new ObservableTransformer() {

    @Override

    public ObservableSource apply(@NonNull Observable upstream) {

    final Object o1 = new Object();

    final Object o2 = new Object();

    return Observable.zip(

    // 这里不能用 merge() 因为 merge() 不保证顺序

    // 使用 concat() 保证顺序, 与一个事件合并, 该事件为了队列有数据

    Observable.concat(upstream

    .compose(RxUtil.rxSchedulerHelper())

    .doOnEach(new Consumer>() {

    @Override

    public void accept(@NonNull Notification tNotification) throws Exception {

    if (tNotification.isOnNext()) {

    // 执行onNext()和onComplete()

    // 在请求B出错的情况下, 可能不执行onComplete()

    // 所以onNext()完 执行 onComplete() 也是一样的

    onNext.accept(tNotification.getValue());

    onComplete.run();

    } else if (tNotification.isOnError()) {

    onError.accept(tNotification.getError());

    }

    }

    })

    , Observable.just(o1)) // 到这里为请求A

    , Observable.concat(Observable.just(o2), source2

    .compose(RxUtil.rxSchedulerHelper())) // 到这里为请求B

    , new BiFunction() {

    @Override

    public Object apply(@NonNull Object t, @NonNull Object k) throws Exception {

    if (t == o1){ //次流

    source2Exc.accept((K) k); //执行请求B的结果

    }

    return new Object();

    }

    }, true); // delayError 设置为true

    }

    };

    }

    请求A队列的事件依次为 A请求, 空事件

    请求B队列的事件依次为 空事件, B请求

    zip() 的 apply() 方法需要配对, 也就是说如果请求A队列为一个事件, 请求B队列为两个事件, 那么apply(), 只会执行一次.

    现在该方法, 已经实现了我的业务逻辑了.

    并行请求A和B

    A先处理结果, B在处理结果

    B出错, A还没有请求完成, A依然继续请求, 并处理结果

    如果A请求出错, 那么不管B比A先完成还是后完成的请求都不会接着执行下去

    照着这个思路, 也可以继续拓展.

    展开全文
  • 面试遇到的ajax请求串行和并行问题

    千次阅读 2016-12-16 10:03:50
    1.有三个ajax请求,如何让这三个ajax请求串行执行,即第一个执行完成后在执行另一个? 我回答的是判断上一个请求返回结果,执行完成之后在执行下一个,对吗? 2.如何让他们并行执行,然后三个请求都执行完成后,再...
  • Ajax请求串行并行问题

    千次阅读 2018-10-10 19:02:09
    如何让他们并行执行,然后三个请求都执行完成后,再执行某个操作? 其考察内容是同步异步。 源网址 https://blog.csdn.net/david___/article/details/53689270 感觉作者写的很不错,转一下 //串行执行分两种...
  • Promise 并行和串行理解

    千次阅读 2019-02-19 11:08:29
    promise主要是针对异步请求,这里...串行:一个异步请求完了之后在进行下一个请求 首先定义一些promise实例 并行: var promises = function () { return [1000, 2000, 3000].map(current =&gt; { return...
  • 这样串行和并行功能也就完成了。 第六:下面是在as上的具体使用实例。 public class MainActivity extends AppCompatActivity { private static final String TAG = "dasfhadksfhakf"; TangPoetryBean ...
  • 在开发中老大让我做这样一件事情,封装一个全局公共方法处理网络请求数据,因为这是一个树结构的数据,每次请求都要做一堆空指针判断的逻辑,这样每次写起来就很烦。 每次这样肯定是不能接受的,因为树的根节点第...
  • 并发请求串行执行

    2020-06-20 23:44:40
    站点收到并发请求需要串行处理,或者并行执行的业务某个环节需要串行处理。 二、分析 1,只能针对操作同一条数据的业务处理串行处理,整体必须并行处理。 2,因为执行速度很快,发生并发时,最好每一条都被执行,...
  • RxJava实现串行任务和并行任务

    千次阅读 2019-09-16 14:53:14
    串行和并行,是针对任务这个概念而来的,也就是串行任务和并行任务。 那我们需要了解一下什么是任务。 用一个http网络请求来看,这一个网络请求就是一个任务。它包含了发送请求、后台处理、处理返回数据这几个步骤。...
  • 我们都知道,php是串行请求的,我们在碰到以下几个场景的时候,php的效率会变的比较低下:1:一个请求,在输出结果前,有比较长时间的耗时操作(但这个操作不影响输出结果),这时候,客户端会等待比较长的时间。...
  • 将用户请求放入消息队列,并反馈给用户,系统添加购物车程序已经启动,你可以关闭浏览器或者关闭应 用程序了。后续程序会慢慢地去写入数据库中去。这就是异步同步的差异。但是用户没有卡死的感觉, 一般会有系统...
  • 2.串行口的典型代表是RS-232C及其兼容插口,有9针25针两类。 25针串行口具有20mA电流环接口功能,用9、11、18、25针来实现。 其针脚功能如下:  针脚 功能 针脚 功能  1 未用  2 发出数据(TXD) 11 数据发送...
  • 任务61:AJAX中的串行和并行(回调地狱) 1.Promise简介 Promise是ES6中新增的一个内置类:它是一种“承诺“设计模式,主要是有效规划异步编程的代码, 尤其是再处理AJAX异步请求的“回调地狱”上有很大的帮助。 2....
  •  并行发出请求所消耗的时延约等于返回最慢的一个请求, 而串行的时延则是所有请求时延之. 如果是jQuery的话可以调用 jQuery.when(deferreds) 以下为我编写的一个JS 并发AJAX请求类. 实现思想是使用一个计数器...
  • 1. 同步异步  关注的是消息的通信机制,描述的是一种行为方式,是多个任务之间的关系。 ① 同步: 调用者主动等待...② 异步:调用者发送请求请求,不会专职等待被调用方返回结果,当被调用方有结果之后,再通...
  • 串行和并行 并行和并发 高并发 串行和并行 串行就是大家排队一个一个来,并行就是大家一起来。 并行和并发 并行:在同一时刻,有多个任务(程序)同时执行 并发:...
  • 串行接收并行发送FIFO

    2012-01-05 00:17:55
    一个串行接收,并行发送的缓存器,其数据存储使用双端口SRAM(一读一写)实现,SRAM大小为深64、宽32位(64字×32位,使用提供的双端口SRAM见目录rf2shd4)。缓存器按一位串行输入接收数据,缓存器位置全满后不再...
  • 为什么并行优于串行并行的特点是同一时间可以干别的事情,在系统优化的过程中很常见的一点就是接口请求合并,合并请求内部也要做并行处理,否则时间上优势不大。并行最大的好处就是:可以在同一时间内做不同的业务...
  • 这里写目录标题串行并行(数据传送方式)同步异步(通信方式)操作系统总结 在学习过程中经常会遇到这几个词,尤其是操作系统计算机组成。今天来探究一下 串行并行(数据传送方式) 1.并行通讯:同一时刻,可以...
  • requests发送请求串行的,即阻塞的。发送完一条请求才能发送另一条请求。 为了提升测试效率,一般我们需要并行发送请求 这里可以使用多线程,或者协程,gevent或者aiohttp,然而使用起来,都相对麻.
  • 并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件(多核线程)在同一时刻发生;而并发是指两个或多个事件(进程或者程序)在同一时间间隔内发生。计...
  • 并行和并发的区别

    2020-11-30 00:31:49
    并行: 某一时刻同时执行, 例如多核 CPU 同时执行任务. 并行的反义词是串行 并发: 某段时间间隔内发生即可, 不要求必须同一时刻, 例如 5s 内请求接口 100 次 并行和并发并不是互斥的
  • sclk为输入主钟,data[3:0]为输入的四位数据,ack为请求发送数据信号(请求后才有数据发送到data[3:0]),数据流用sclsda两条线传输。第二个模块(M2)接收以简化I2C协议通过sclsda传输来的数据,并转化为相应16...
  • 并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件(多核线程)在同一时刻发生;而并发是指两个或多个事件(进程或者程序)在同一时间间隔内发生。计算机在宏观上...
  • RxHttp 一条链发送请求,新一代Http请求神器(一)

    万次阅读 热门讨论 2019-04-23 07:34:56
    RxHttp是基于OkHttp的二次封装,并于RxJava做到无缝衔接,一条链就能发送一个完整的请求。主要功能如下: - 支持Get、Post、Put、Delete等任意请求方式,可自定义请求方式 ... - 支持请求串行和并行

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 249
精华内容 99
关键字:

并行请求和串行请求