有没有办法更有效地展平这个承诺链(涉及捕获链接)?
Is there a way to flatten this promise chain more effectively (involves chaining on catch)?
假设一个函数返回自定义承诺。为了这个例子,我们假设需要一个自定义承诺:
(注意:环境是 AngularJS [即 1.x] 执行 ES5)
function doMyFunction() {
var d = $q.defer();
do1()
.then (function () { return do2(); }) //P1
.then (function () { return do3(); }) // P2
.then {function () {console.log ("All good"); d.resolve(true); return d.promise;}) // P3
.catch (function () {
console.log ("Oh no");
fallback1()
.then (function () {
console.log ("Ah this fallback1 worked");
d.resolve(true);
return d.promise;
}, function () {
console.log ("Oh no, fallback failed, do I have to go through nested hell to now try fallback 2?");
d.resolve(false);
return d.promise;
});
return d.promise;
}
如上所述,我正在尝试按顺序尝试不同的方法,只有在前一种方法失败的情况下。
如果我尝试像这样压平它:
// lets start from the last promise above
.then {function () {console.log ("All good"); d.resolve(true); return d.promise;}) // P3
.catch (function () { return fallback1(); })
.then (function () { d.resolve(true); return d.promise; }) // P4
.catch (function () {})
这实际上行不通,因为 P3 成功时也会执行 P4。
如果我需要按顺序尝试多个基于 promise 的函数并且仅当前一个函数失败时,处理这种情况的好方法是什么?
另外,我不确定我是否真的可以.then().catch().then().catch()
有没有一种干净的方法可以避免在这种情况下嵌套地狱?
您是否针对 javascript 调查过 async/await?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
验证浏览器兼容性是否可以接受。
async function() {
let first, second, third, fourth;
try {
first = await do1();
second = await do2();
third = await do3();
fourth = await do4();
return fourth;
} catch(e){
console.log(e + ' failed. Reverting back to the first')
}
return first;
}
我想知道。未经测试,但由于它们都是未定义的,如果您只想 return 最后接受的项目,那么您可以在 catch 之后测试以下最终 return,如下所示:
return fourth || third || second || first;
它应该只是 return 第一个有效结果,这将是具有可接受值的最终结果。
正确的 promises 链接应该如下所示
function doWholeWork(){
return work1().
then((work1Result)=>{
return work2();
})
then((work2Result)=>{
return work3();
})
.catch(error=>{
console.log("Some error happened", error)
});
}
您可以只链接 catch
方法调用,因为 catch
也 returns 一个可以解决或拒绝的承诺。所以你实际上会在 catch
回调中执行下一个回退:
function perform(i) { // Some mock function for this demo returning a promise
return new Promise((resolve, reject) => {
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) reject("some error"); else resolve(i);
}, 100);
});
}
function doMyFunction() {
return perform(1)
.catch( () => perform(2) )
.catch( () => perform(3) )
.catch( () => perform(4) ) // <-- this is the first one that resolves
.catch( () => perform(5) ) // <-- this callback is never executed
.catch( () => perform(6) ); // <-- (idem)
}
doMyFunction().then( (i) => console.log('Success with step ' + i) ); // <-- final result
请注意,对于 AngularJS 下的 ES5 代码,第一个模拟函数如下所示:
function perform(i) { // Some function returning a promise
var d = q$.defer();
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) d.reject("some error"); else d.resolve(i);
}, 100);
return d.promise();
}
结合其他处理器
如果您的逻辑中间有其他处理程序,您可以在函数中使用上述原则,并调用该函数提供所有可能的回退:
function perform(i) { // Some mock function for this demo returning a promise
return new Promise((resolve, reject) => {
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) reject("some error"); else resolve(i);
}, 100);
});
}
function tryAndFallback(fallbacks) {
return (function loop(fallbacks) {
if (!fallbacks.length) return Promise.reject("Nothing worked!");
return fallbacks[0]().catch( () => loop(fallbacks.slice(1)) );
})(fallbacks);
}
function doMyFunction() {
return Promise.resolve() // <-- some promise that is just fine
// Now a task that has a few fallbacks
.then( () => tryAndFallback([() => perform(2),
() => perform(3),
() => perform(4)]) )
.then( () => console.log('more work can be done here') );
}
doMyFunction().then( (i) => console.log('All done') ); // <-- final result
假设一个函数返回自定义承诺。为了这个例子,我们假设需要一个自定义承诺:
(注意:环境是 AngularJS [即 1.x] 执行 ES5)
function doMyFunction() {
var d = $q.defer();
do1()
.then (function () { return do2(); }) //P1
.then (function () { return do3(); }) // P2
.then {function () {console.log ("All good"); d.resolve(true); return d.promise;}) // P3
.catch (function () {
console.log ("Oh no");
fallback1()
.then (function () {
console.log ("Ah this fallback1 worked");
d.resolve(true);
return d.promise;
}, function () {
console.log ("Oh no, fallback failed, do I have to go through nested hell to now try fallback 2?");
d.resolve(false);
return d.promise;
});
return d.promise;
}
如上所述,我正在尝试按顺序尝试不同的方法,只有在前一种方法失败的情况下。
如果我尝试像这样压平它:
// lets start from the last promise above
.then {function () {console.log ("All good"); d.resolve(true); return d.promise;}) // P3
.catch (function () { return fallback1(); })
.then (function () { d.resolve(true); return d.promise; }) // P4
.catch (function () {})
这实际上行不通,因为 P3 成功时也会执行 P4。
如果我需要按顺序尝试多个基于 promise 的函数并且仅当前一个函数失败时,处理这种情况的好方法是什么?
另外,我不确定我是否真的可以.then().catch().then().catch()
有没有一种干净的方法可以避免在这种情况下嵌套地狱?
您是否针对 javascript 调查过 async/await? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
验证浏览器兼容性是否可以接受。
async function() {
let first, second, third, fourth;
try {
first = await do1();
second = await do2();
third = await do3();
fourth = await do4();
return fourth;
} catch(e){
console.log(e + ' failed. Reverting back to the first')
}
return first;
}
我想知道。未经测试,但由于它们都是未定义的,如果您只想 return 最后接受的项目,那么您可以在 catch 之后测试以下最终 return,如下所示:
return fourth || third || second || first;
它应该只是 return 第一个有效结果,这将是具有可接受值的最终结果。
正确的 promises 链接应该如下所示
function doWholeWork(){
return work1().
then((work1Result)=>{
return work2();
})
then((work2Result)=>{
return work3();
})
.catch(error=>{
console.log("Some error happened", error)
});
}
您可以只链接 catch
方法调用,因为 catch
也 returns 一个可以解决或拒绝的承诺。所以你实际上会在 catch
回调中执行下一个回退:
function perform(i) { // Some mock function for this demo returning a promise
return new Promise((resolve, reject) => {
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) reject("some error"); else resolve(i);
}, 100);
});
}
function doMyFunction() {
return perform(1)
.catch( () => perform(2) )
.catch( () => perform(3) )
.catch( () => perform(4) ) // <-- this is the first one that resolves
.catch( () => perform(5) ) // <-- this callback is never executed
.catch( () => perform(6) ); // <-- (idem)
}
doMyFunction().then( (i) => console.log('Success with step ' + i) ); // <-- final result
请注意,对于 AngularJS 下的 ES5 代码,第一个模拟函数如下所示:
function perform(i) { // Some function returning a promise
var d = q$.defer();
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) d.reject("some error"); else d.resolve(i);
}, 100);
return d.promise();
}
结合其他处理器
如果您的逻辑中间有其他处理程序,您可以在函数中使用上述原则,并调用该函数提供所有可能的回退:
function perform(i) { // Some mock function for this demo returning a promise
return new Promise((resolve, reject) => {
console.log('try with ' + i);
setTimeout(() => {
if (i < 4) reject("some error"); else resolve(i);
}, 100);
});
}
function tryAndFallback(fallbacks) {
return (function loop(fallbacks) {
if (!fallbacks.length) return Promise.reject("Nothing worked!");
return fallbacks[0]().catch( () => loop(fallbacks.slice(1)) );
})(fallbacks);
}
function doMyFunction() {
return Promise.resolve() // <-- some promise that is just fine
// Now a task that has a few fallbacks
.then( () => tryAndFallback([() => perform(2),
() => perform(3),
() => perform(4)]) )
.then( () => console.log('more work can be done here') );
}
doMyFunction().then( (i) => console.log('All done') ); // <-- final result