重试承诺步骤

时间:2016-06-23 13:40:47

标签: javascript promise es6-promise

假设我有以下Promise链:

var result = Promise.resolve(filename)
    .then(unpackDataFromFile)
    .then(transformData)
    .then(compileDara)
    .then(writeData);

现在我不仅有一个transformData函数,而且有两个或更多,存储在一个数组中。我想尝试第一个,如果compileData函数失败,请尝试第二个,依此类推,直到compileData成功或transformData函数数组耗尽。

有人能给我一个如何实现这个的例子吗?

运行所有transformData函数并将结果数组赋给compileData不是一个选项,因为函数非常昂贵,我希望尽可能少地运行它们。

transformData本身也会返回一个Promise,如果有帮助的话。

3 个答案:

答案 0 :(得分:1)

我首先要分离尝试许多承诺的概念,直到成功为止:

   <?php
    ob_start();
    //session_start(); 

    if(isset($_GET['lang'])) {
    $lang = $_GET['lang'];
    } else {
    $lang = 'geo';
    }

    //require_once('includes/session.php');
    require_once('classes/class.user.php');
    $user = new USER('');

    if($user->is_loggedin()!="")
    {   
        $user_logout->redirect('index.php');

    }
    if(isset($_GET['logout']) && $_GET['logout']=="true")
    {   $user->Logout();
    echo "YOU ARE LOGGED OUT";
        $user->redirect('index.php');
    }
    ?>

现在编写一个处理程序,它尝试转换和编译的每个组合:

function tryMultiple([promise, ...rest]) {
  if (!promise) throw new Error("no more to try");
  return promise.catch(() => tryMultiple(rest));
}

现在顶级只是:

function transformAndCompile(transformers) {
  return function(data) {
    return tryMultiple(transformers.map(t => t(data).then(compileData)));
  };
}

顺便说一下,var result = Promise.resolve(filename) .then(unpackDataFromFile) .then(transformAndCompile(transformers)) .then(writeData); 只是说Promise.resolve(filename).then(unpackDataFromFile)的迂回方式。

答案 1 :(得分:0)

您可以这样做:

// various transformer functions to try in order to be tried
var transformers = [f1, f2, f3, f4];    

function transformFile(filename) {
    // initialize tIndex to select next transformer function
    var tIndex = 0;
    var p = unpackDataFromFile(filename);

    function run() {
          return p.then(transformers[tIndex++])
          .then(compileData)
          .catch(function(err) {
              if (tIndex < transformers.length) {
                // execute the next transformer, returning
                // a promise so it is linked into the chain
                return run();
              } else {
                // out of transformers, so reject and stop
                throw new Error("No transformer succeeded");
              }
          }).then(writeData);

    }
    return run();
}

transformFile("someData.txt").then(function(finalResult) {
    // succeeded here
}).catch(function(err) {
    // error here
});

以下是如何运作的:

  1. 设置索引到变换器函数数组的tIndex变量。
  2. 致电unpackDataFromFile(filename)并保存由此产生的承诺。
  3. 然后使用第一个变换器执行序列p.then(transformer).then(compileData)。如果成功,则调用writeData并返回生成的promise。
  4. 如果变压器或compileData失败,则转到下一个变换器功能并重新开始。使这项工作的关键是在.catch()处理程序中,它返回一个新的promise,它链接到最初返回的promise。每次对run()的新调用都链接到unpackDataFromFile()的原始承诺,允许您重复使用该结果。
  5. 这是一个更通用的实现,它为一个迭代的数组构成一个迭代器,直到迭代器回调返回一个满足的promise。

    // Iterate an array using an iterator that returns a promise
    // Stop iterating as soon as you get a fulfilled promise from the iterator
    // Pass:
    //    p - Initial promise (can be just Promise.resolve(data))
    //    array - array of items to pass to the iterator one at a time
    //    fn - iterator function that returns a promise
    //         iterator called as fn(data, item)
    //             data - fulfilled value of promise passed in
    //             item - array item for this iteration
    function iterateAsyncUntilSuccess(p, array, fn) {
        var index = 0;
    
        function next() {
            if (index < array.length) {
                var item = array[index++];
                return p.then(function(data) {
                    return fn(data, item).catch(function(err) {
                        // if this one fails, try the next one
                        return next();
                    });
                });
            } else {
                return Promise.reject(new Error("End of data with no operation successful"));
            }
        }
    
        return next();
    }
    
    // Usage:
    // various transformer functions to try in order to be tried
    var transformers = [f1, f2, f3, f4];    
    
    iterateAsyncUntil(unpackDataFromFile(filename), transformers, function(data, item) {
        return item(data).then(compileData);
    }).then(writeData).then(function(result) {
        // successfully completed here
    }).catch(function(err) {
        // error here
    });
    

答案 2 :(得分:-1)

以下内容应该最符合您的要求:

var transformers = [transformData, transformData2];

var result = unpackDataFromFile(filename)
  .then(function transpile(data, i = 0) {
    return transformers[i](data).then(compileData)
      .catch(e => ++i < transformers.length? transpile(data, i) : Promise.reject(e));
  })
  .then(writeData);

基本上你使用.catch()递归变形金刚阵列。