如何在第一次成功之前按顺序多次执行异步函数

时间:2016-05-20 04:54:20

标签: scala

假设我有一个功能

def request(url: String): Future[String]

需要编写一个函数

def requestFirst(urls: List[String]): Future[String]

按顺序调用request(url)直到它成功完成(在这种情况下返回成功的值)或所有url的请求失败(在这种情况下返回所有失败)。

如何在Scala中完成?

2 个答案:

答案 0 :(得分:2)

/* cpm.c
   Useful functions for Workshop E 
*/
#include"cpm.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

#define BUFFERSIZE      4096

void oops(char *, char *);
unsigned char bitmap[12];
struct CPMdirent directory[64];

int toggle_bit(int block) /*directory - initilise disk*/
{

    int elem=block/8;
    int pos=block%8;
    int mask=1<<pos;

    bitmap[elem]^=mask;

    return bitmap[elem]&mask;
}


int block_status(int block)
{
    int elem=block/8;
    int pos=block%8;
    int mask=1<<pos;

    return bitmap[elem]&mask;
}


int main(int argv, char *av[])
{
    int     choice = 0;
    int     input_fd, output_fd, n_chars, status;

    char    buffer[BUFFERSIZE];
    char    cwd[1024];
    char    file_name[9];

    FILE    *fptr;

    struct  dirent *dir;
    DIR     *dp;

    do
    {
        printf("Please choose a task (enter the number)\n");
        printf("1. Intialise Disk\n");

        switch(choice)
        {
            /*Intialising the disk (store directory in arrays)*/
            case 1:
                printf("~~~~~~~~~~~~ Initialising the disk ~~~~~~~~~~~~\n");
                toggle_bit(0);
                directory[0].usercode;
                directory[0].filename[9];
                directory[0].filetype[4];
                directory[0].extent;
                directory[0].blockcount;
                directory[0].blocks[16];
                printf("\nDisk sucessfully initialised.\n");
                break;

    }
    while(choice != 8);

}

void oops(char *s1, char *s2)
{
    fprintf(stderr,"Error: %s ", s1);
    perror(s2);
    exit(1);
}

OR

def requestFirst(urls: List[String]): Future[String] = {
  val default: Future[String] = Future.failed(new scala.Exception("all failed"))
  urls.foldLeft(default)((prevFuture, currentUrl) => {
    prevFuture fallbackTo (request(currentUrl))
  })
}

答案 1 :(得分:0)

这是我根据@ parnav-shukla答案提出的:

def requestFirst(urls: List[String]): Future[String] = {
  def requestFirstInternal(urlSubset: List[String], errors: Seq[String]): Future[String] = {
    if(urlSubset.isEmpty) {
      Future.failed(new Exception(errors.mkString("\n")))
    } else {
      request(urlSubset.head) recoverWith { t =>
        requestFirstInternal(urlSubset.tail, errors ++ Seq(t.getMessage))
      }
    }
  }
  requestFirstInternal(urls, Seq.empty)
}