javascript - 解决带有嵌套 promise 的对象的美丽方法?

标签 javascript express promise loopbackjs bluebird

在构建自定义端点时,我经常需要解析包含 promise 的复杂对象。

举个例子:

给定已知用户的 idemployeeIdmemberGroupsIds(一个数组):

var loginResponse = {
    userprofile : getProfile(id)
    companyInfo : {
        company : getCompany(employeeId)
        companyRelations : getPriviligedInfo(employeeId)
    }
    groups : getGroups(memberGroupsIds)
}

此逻辑适用于仅返回其值的同步函数。但是对于返回 promise 的函数,我必须手动将它们全部推送到一个数组中,以确保在使用最终对象之前解析它们。

我发现上面的代码非常容易理解,我正在寻找一个签名来提供其中的一些,同时仍然确保在将最终对象发送给客户端之前解决 promise 。

问题不在于让它发挥作用,而在于让它美观且易于阅读。

最好的答案是确保将值返回到对象中的预期键,并且所有 promise 都并行解决,同时保持与同步函数的结构在某种程度上兼容的结构。

或者,如果我没捕获要点,看错了,我应该怎么看?

最佳答案

您可以使用下面的辅助函数。它接受一个对象并返回一个 promise ,该 promise 在所有嵌套 promise 都已解决时解决。返回的 promise 将提供相同对象的值,该对象将发生变异,所有嵌入的 promise 都被相应的值替换。

function promiseRecursive(obj) {
    const getPromises = obj =>
        Object.keys(obj).reduce( (acc, key) =>
            Object(obj[key]) !== obj[key]
                ? acc
                : acc.concat(
                    typeof obj[key].then === "function"
                        ? [[obj, key]]
                        : getPromises(obj[key])
                  )
        , []);
    const all = getPromises(obj);
    return Promise.all(all.map(([obj, key]) => obj[key])).then( responses =>
        (all.forEach( ([obj, key], i) => obj[key] = responses[i]), obj) 
    );
}

你可以这样调用它:

var loginResponsePromise = promiseRecursive({
    userprofile : getProfile(10),
    companyInfo : {
        company : getCompany(101),
        companyRelations : getPriviligedInfo(101)
    },
    groups : getGroups([5])
});

function promiseRecursive(obj) {
    const getPromises = obj =>
        Object.keys(obj).reduce( (acc, key) =>
            Object(obj[key]) !== obj[key] ? acc
                : acc.concat(typeof obj[key].then === "function" ? [[obj, key]] 
                : getPromises(obj[key]))
        , []);
    const all = getPromises(obj);
    return Promise.all(all.map(([obj, key]) => obj[key])).then( responses =>
        (all.forEach( ([obj, key], i) => obj[key] = responses[i]), obj) 
    );
}

// Example promise-returning functions
const wait = ms => new Promise( resolve => setTimeout(resolve, ms) ),
    getProfile = id => wait(100).then(_ => ({userName: 'user' + id,id})),
    getCompany = employeeId => wait(200).then(_ => ({employeeName: 'employee' + employeeId, employeeId})),
    getPriviligedInfo = employeeId => wait(500).then(_ => ({privs: 'privInfo' + employeeId, employeeId})),
    getGroups = memberGroupsIds => wait(400).then(_ => ({groups: ['group' + memberGroupsIds[0]],memberGroupsIds}));

// Sample input passed to `promiseRecursive` function
const loginResponsePromise = promiseRecursive({
    userprofile : getProfile(10),
    companyInfo : {
        company : getCompany(101),
        companyRelations : getPriviligedInfo(101)
    },
    groups : getGroups([5])
});

// Display the resolved object
loginResponsePromise.then( o => console.log(o) );
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 解决带有嵌套 promise 的对象的美丽方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44065564/

相关文章:

node.js - Express API REST 过滤数据 MongoDB

javascript - 将参数传递给angularjs中的promise回调

javascript - 为什么我的 SetInterval 中没有调用我的函数?

mysql - 从 mySQL 返回未定义

node.js - 在 Node.js Express 路由/ Controller 中对基于 Promise 的代码进行单元测试

javascript - jQuery 推迟了 : Nesting promises in methods, 最后一次回调太早

javascript - 在 Node 的 Promise 中调用类的其他函数

javascript - noUiSlider 链接错误

javascript - 仅当父级 div 有 id 属性时才选择它

javascript - 在 typescript 中使用@waves/waves-crypto 在waves 区 block 链上创建加密地址时出错