2017-01-16 6 views
6

Существуют такие методы, как Q.reduce и Q.all, которые помогают сгладить цепочку обещаний в конкретном случае разнородных коллекций обещаний. Ум, однако, общий случай:Как правильно выразить произвольные цепочки Promise без «пирамид отступов»?

const F = (x) => x; 
const a = F(1); 
const b = F(2); 
const c = F(a + b); 
const d = F(a + c); 
const e = F(b + c); 
console.log(e); 

То есть, последовательность заданий, на котором каждый член зависит от произвольных ранее определенных условий. Предположим, что F асинхронный вызов:

const F = (x) => Q.delay(1000).return(x); 

я могу думать ни в коем случае, чтобы выразить эту схему без создания отступа пирамиды:

F(100).then(a => 
    F(200).then(b => 
    F(a+b).then(c => 
     F(a+c).then(d => 
     F(b+c).then(e => 
      F(d+e).then(f => 
      console.log(f) 
     ) 
     ) 
    ) 
    ) 
) 
); 

Обратите внимание, что с помощью возвращаемых значений не будет работать:

F(100).then(a => F(200)) 
    .then(b => F(a+b)) 
    .then(c => F(a+c)) 
    .then(d => F(b+c)) 
    .then(e => F(d+e)) 
    .then(f => console.log(f)); 

Так как, например, a не будет занимать область действия на второй линии. Каков правильный способ справиться с этой ситуацией?

+2

Различные методы здесь: [Как связать предыдущие результаты с обещаниями] (http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863 # 28714863). На самом деле, этот вопрос может быть одним из двух. – jfriend00

+0

@ jfriend00: Это определенно дубликат того же самого, что и дубликат, хорошая находка. –

+0

Определенно дубликат, я вижу. Тем не менее, я думаю, что эта тема становится более поучительной. – MaiaVictor

ответ

3

Из-за способа, что последующие операции опираются на несколько битов предыдущих операций, ваш выбор:

  1. Делайте то, что вы сделали

  2. Поместите переменные вне цепи и назначить их как вы идете

  3. Есть все вещи, проходящие вокруг объекта с a, b, и такими на нем как свойства

# 1 это то, что я придерживаюсь, за исключением действительно хорошая причина сделать любой из двух других. К счастью, такое накопление редко идет настолько глубоко, как показано в вашем вопросе.


Если вы хотите принять async/await рано (the proposal закончена, они будут в ES2017, и вы можете использовать их теперь с transpiler), а затем увидеть Sterling's answer для того, как они могли бы упростить , Вот рабочий пример (live on Babel's REPL):

const F = x => { 
    return new Promise(resolve => { 
    setTimeout(() => { 
     resolve(x); 
    }, 100); 
    }); 
}; 
(async() => { 
    const a = await F(100); 
    const b = await F(200); 
    const c = await F(a+b); 
    const d = await F(a+c); 
    const e = await F(b+c); 
    const f = await F(d+e); 
    console.log(f); 
})(); 
+0

async/await может помочь с областью действия, или вы можете использовать Promise.all() iirc, чтобы упростить параметры цепочки. (Я использовал async lib для узла, и он упрощает прохождение параметров) –

+0

@SterlingArcher: вещь 'async' /' await' является ** очень хорошей точкой (и если вы транслируете, вы можете использовать ее Теперь). –

+0

Написал гораздо лучший ответ, ха-ха, мы можем поблагодарить Багаж в чате JS за эту идею. –

3

Вторая попытка. @Load в чате JS предложили использовать Async/Await, чтобы сохранить объем ваших параметров.

let a = await F(200); 
let b = await F(a + 100); 
let c = await F(a + b); 
//... etc, all inside an async function 

Вы также можете использовать Promise.all или (это мой опыт) я использовал async LIB, чтобы помочь водопаду этих вопросов.

async.waterfall([ 
    (callback) => { 
     let a = F(200); 
     callback(null, a) 
    }, (a, callback) => { 
     let b = F(a+b); 
     callback(null, b); 
    }, //etc down the chain 
]); 

Я думаю Promise.all бы управлять лучше, чем асинхронным Lib, но асинхронной/ждать являются симпатичными методами здесь, хотя это потребует поддержки ES2017/transpiling.

2

Async/ждут решить эту проблему довольно красиво, я думаю;

async function runAsync(){ 
    const F = async (x) => x; 
    const a = await F(1); 
    const b = await F(2); 
    const c = await F(a + b); 
    const d = await F(a + c); 
    const e = await F(b + c); 
    console.log(e); 
} 

function runSync(){ 
    const F = (x) => x; 
    const a = F(1); 
    const b = F(2); 
    const c = F(a + b); 
    const d = F(a + c); 
    const e = F(b + c); 
    console.log(e); 
} 

runSync(); //5 
runAsync(); //5 

это будет работать изначально с узлом 7 с помощью node --harmony-async-await example

К сожалению, вы, вероятно, нужно transpile вниз для общего пользования, и выход может быть довольно большим.

+0

есть nodejs async/модуль ожидания, который делает это очень хорошо –

 Смежные вопросы

  • Нет связанных вопросов^_^