Есть ли способ более эффективно сгладить эту цепочку обещаний (включает в себя цепочку прилова)? - PullRequest
0 голосов
/ 31 мая 2018

Предположим, что функция возвращает пользовательское обещание.В этом примере давайте предположим, что требуется пользовательское обещание:

(Примечание: среда 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 () {})

Это на самом деле не работает, потому что P4 выполняется, когда P3 также успешен.

Что такоехороший подход для обработки случая, когда мне нужно попробовать несколько функций, основанных на обещаниях, последовательно и только в случае сбоя предыдущей?

Кроме того, я не уверен, смогу ли я действительно выполнить .then().catch().then().catch()

Есть ли чистый подход, чтобы избежать гнезда ада в таких ситуациях?

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Правильные цепочки обещаний должны выглядеть следующим образом

function doWholeWork(){
return work1().
then((work1Result)=>{
return work2();
})
then((work2Result)=>{
return work3();
})
.catch(error=>{
console.log("Some error happened", error)
});
}
0 голосов
/ 31 мая 2018

Вы можете просто связать catch вызовы методов, так как catch также возвращает обещание, которое может быть разрешено или отклонено.Таким образом, вы фактически выполняете следующий откат в обратном вызове 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

Обратите внимание, что с кодом ES5 в AngularJS первая функция макета будет выглядеть следующим образом:

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
0 голосов
/ 31 мая 2018

Вы смотрели в async / await для javascript?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 fourth || third || second || first;

Должно быть возвращено только первый действительный результатэто будет конечный результат, который имеет приемлемое значение.

...