假设我有以下Promise链:
var result = Promise.resolve(filename)
.then(unpackDataFromFile)
.then(transformData)
.then(compileDara)
.then(writeData);
现在我不仅有一个transformData
函数,而且有两个或更多,存储在一个数组中。我想尝试第一个,如果compileData
函数失败,请尝试第二个,依此类推,直到compileData
成功或transformData
函数数组耗尽。
有人能给我一个如何实现这个的例子吗?
运行所有transformData
函数并将结果数组赋给compileData
不是一个选项,因为函数非常昂贵,我希望尽可能少地运行它们。
transformData
本身也会返回一个Promise,如果有帮助的话。
答案 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
});
以下是如何运作的:
tIndex
变量。unpackDataFromFile(filename)
并保存由此产生的承诺。p.then(transformer).then(compileData)
。如果成功,则调用writeData并返回生成的promise。.catch()
处理程序中,它返回一个新的promise,它链接到最初返回的promise。每次对run()
的新调用都链接到unpackDataFromFile()
的原始承诺,允许您重复使用该结果。这是一个更通用的实现,它为一个迭代的数组构成一个迭代器,直到迭代器回调返回一个满足的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()
递归变形金刚阵列。