在不通过变量的情况下解决承诺

时间:2018-04-10 02:17:27

标签: javascript asynchronous promise chaining

我正在学习使用promises并尝试使用函数式编程来实现代码模块化。我的问题是,当我通过then()链进展时,我通过中间then()调用传递参数,以便以后使用函数。

这种感觉是不必要的,我想我错过了树林。

function getSession(user, pass) {
    return new Promise((resolve) => {
        // do something with user and pass
        resolve(session)
    })
}


function getAccount(session) {
    return new Promise((resolve) => {
        // do something with session - pass through session
        resolve([session, account])
    })
}

function doThing(session, account) {
    return new Promise((resolve) => {
        // do something with account - pass through session
        resolve([session, thing])
    })
}

function doOtherThing(session, thing) {
    return new Promise((resolve) => {
        // do something with session and thing
        resolve(otherThing)
    })
}

let example = getSession(user, pass).then(getAccount).then(doThing).then(doOtherThing)

例如,doThing()传递sessionaccount,但仅对account执行某些操作。但是,由于doOtherThing()需要session,我会通过会话实例,以便该函数可以使用它。

因此,要消除传递这些额外变量,我想做

之类的东西
function getAccount(session) {
    return new Promise((resolve) => {
        // do something with session
        resolve(account)
    })
}

function doThing(account) {
    return new Promise((resolve) => {
        // do something with account
        resolve(thing)
    })
}

let session = getSession(user, pass)
let thing = getSession(user, pass).then(getAccount).then(doThing)
let example = doOtherThing(session, thing)

正如您所看到的,这些函数中的大多数都返回了一个promise,因此我可以通过在其他地方链接来改进代码模块化。因此,sessionthing变量被分配了承诺。

但是在这种情况下,我只想解决sessionthing中的两个承诺,然后在doOtherThing(session, thing)中使用

我试过像

这样的东西
let session = getSession(user, pass).resolve()
let thing = getSession(user, pass).then(getAccount).then(doThing).resolve()

let example = doOtherThing(session.resolve(), thing.resolve())

但我将resolve is not a function视为错误。

我也知道

let session = getSession(user, pass)
let thing = getSession(user, pass).then(getAccount).doThing(account)
let example = doOtherThing(session, thing)

没有意义,因为两个变量中的promise都需要在传递给doOtherThing()之前解决,但是我想知道如何做到这一点 - 所以这是更多伪代码表明我不知道我想通过会议

我看过this question,但我认为我不想做同样的事情。

3 个答案:

答案 0 :(得分:0)

好的,所以我找到了一种方法 - 不确定它是否是最干净的,但它会删除传递变量

let session = getSession(user, pass)
let thing = session.then(getAccount).doThing(account)

Promise.all([session, thing])
    .then((promises => { 
        [session, thing] = promises

        return doOtherThing(session, thing) 
    }))
    .then(otherThing => { console.log(otherThing) })

答案 1 :(得分:0)

这看起来更干净吗?

let session = getSession(user, pass)
let thing = session.then(getAccount).doThing(account)

Promise.all([
  session,
  thing
]).then(data => {
  return doOtherThing(...data)
}).then(anyOtherThing => {
  console.log(anyOtherThing)
}).catch(console.log);

答案 2 :(得分:0)

在查看another answer之后,看起来最干净,最易读的方法是使用async

function getAccount(session) {
    return new Promise((resolve) => {
        // do something with session
        resolve(account)
    })
}

function doThing(account) {
    return new Promise((resolve) => {
        // do something with account
        resolve(thing)
    })
}

const main = async () => {
    let session = await getSession(user, pass)
    let account = await getAccount(session)
    let thing = await doThing(account)
    let otherThing = await doOtherThing(session, account)

    return(otherthing)
}

let otherThingResult = main()

这允许promises以熟悉的同步代码样式执行,并提供许多优点;

  1. 变量不需要通过'链式承诺' 意味着这些已解决的承诺的结果可以是单一的 变量而不是包含所需变量的数组 传递的变量
  2. 反过来允许'链接'承诺函数参数接受 单个变量而不是使用数组的解构增加 代码的可重用性
  3. 在其他代码区域中使用Promise.all()现在提示更多 执行一系列无关承诺的原始功能 异步
  4. 代码缩进率仍然很低,可读性大大提高