【问题标题】:Resolve all promises in an array of json - javascript解析 json 数组中的所有承诺 - javascript
【发布时间】:2018-04-13 13:04:46
【问题描述】:

我需要解析 json 数组中的所有 promise,如下所示:

let list = [
    { 
        id: 1,
        data: new Promise((resolve, reject) => {
            resolve('Cat')
        })
    },
    { 
        id: 2,
        data: new Promise((resolve, reject) => {
            resolve('Dog')
        })
    },
    { 
        id: 3,
        data: new Promise((resolve, reject) => {
            resolve('Mouse')
        })
    }
]

我使用 bluebird 承诺。 我使用 for 循环迭代所有项目,我会知道是否有更优雅的方式。

预期结果:

[ { data: 'Cat', id: 1 },
  { data: 'Dog', id: 2 },
  { data: 'Mouse', id: 3 } ]

【问题讨论】:

  • Promise.all(list.map(x => x.data))?不确定“解决数组中的所有承诺”是什么意思。
  • 预期的结果是什么?实际输入是什么? (您所展示的并不是声称的 JSON,而且这里似乎根本没有理由使用 Promise)。

标签: javascript node.js promise bluebird es6-promise


【解决方案1】:

Promise.all 可能很适合这里:

Promise.all(list.map(entry => entry.data)).then((resolved) => {
  // ...
});

【讨论】:

  • 它解决了承诺,但我将得到一组已解决的值作为结果。我的意思是,有了你的解决方案,我有:list = [Dog, Cat, Mouse]。我想要 list=[{id:1, data: Dog}, ... e 等等...当然我可以生成我需要的数组,但我正在寻找一种更优雅的方式
【解决方案2】:

使用 Promise.all 和一些 JavaScript。

let list = [];
let promise = Promise.all(list.map(entry => entry.data));
promise.then((results) => {
  let final = results.map((result, index) => {
    return {data: result, id: list[index].id};
  });
  console.log(final);
});

【讨论】:

    【解决方案3】:

    你只需要创建一个 promise 数组。你可以用formap 来做

    let promises = []
    
    for(var i=0; i < list.length; i++)
      promises.push(list.data)
    
    Promise.all(promises).then(resultList => { ... }).catch(err => { ... })
    

    或者最简单的可以使用map

    Promise.all(list.map(p => p.data)).then(resultList => { ... }).catch(err => { ... })
    

    【讨论】:

    • 它解决了承诺,但我将得到一组已解决的值作为结果。我的意思是,有了你的解决方案,我有:list = [Dog, Cat, Mouse]。我想要 list=[{id:1, data: Dog}, ... e 等等...当然我可以生成我需要的数组,但我正在寻找一种更优雅的方式
    • @tinytanks 我明白了。然后你应该在你的承诺上添加如下调用:Promise.all(list.map(p =&gt; p.data.then(data =&gt; {...p, data}))).then(resultList =&gt; { ... }).catch(err =&gt; { ... })
    【解决方案4】:

    你可以使用 lodash lib 来最小化你的代码

    const _ = require('lodash');
    
    Promise.all(_.map(list, 'data')).then((data)=>{
        list.map((item,ind)=>{item.data = data[ind]});
        console.log(list);
    })
    

    【讨论】:

    • 它解决了承诺,但我将得到一组已解决的值作为结果。我的意思是,有了你的解决方案,我有:list = [Dog, Cat, Mouse]。我想要 list=[{id:1, data: Dog}, ... e 等等...当然我可以生成我需要的数组,但我正在寻找一种更优雅的方式
    • 那么,加载一个 20k 的库来节省 8 个字符的代码?
    • @Jaromanda 更少的代码意味着更少的错误和干净的代码,因此更优雅,如果你有大项目,你应该使用这些库来消除不需要的琐碎代码。
    • 当然,Promise.map(list, Promise.props) 与您的代码的最短版本 Promise.all(_.map(list, 'data')) 的长度相同……但不需要其他库……更少的代码或更少的库 = 赢得胜利
    • 我同意你的看法:)
    【解决方案5】:

    这应该可以,Promise.all 和 array.map 和其他的一样,但是结果是正确的

    let list = [
        { 
            id: 1,
            data: new Promise((resolve, reject) => {
                resolve('Cat')
            })
        },
        { 
            id: 2,
            data: new Promise((resolve, reject) => {
                resolve('Dog')
            })
        },
        { 
            id: 3,
            data: new Promise((resolve, reject) => {
                resolve('Mouse')
            })
        }
    ]    
    
    Promise.all(list.map(item => item.data.then(data => ({...item, data}))))
    // that's it, that's what you want, the rest is for show now
    .then(results => {
       console.log(results);
    });

    不过,这是 Native Promise ... 您可能需要查看 bluebird 中的 Promise.props 和/或 Promise.map 以获得可能更简单的代码

    其实很简单

    Promise.map(list, Promise.props)
    .then(results => {
        console.log(results);
    });
    

    测试了上面的,是的,就是这么简单 - 下面的 sn-p 有 我自己的 版本的 Promise.mapPromise.props - 并且工作(至少在这种情况下)相同蓝鸟

    Promise.props = obj => {
        const keys = Object.keys(obj);
        return Promise.all(Object.values(obj)).then(results => Object.assign({}, ...results.map((result, index) => ({[keys[index]]: result}))));
    };
    
    Promise.map = (array, fn, thisArg) => Promise.all(Array.from(array, (...args) => fn.apply(thisArg, args)));
    
    let list = [
        { 
            id: 1,
            data: new Promise((resolve, reject) => {
                resolve('Cat')
            })
        },
        { 
            id: 2,
            data: new Promise((resolve, reject) => {
                resolve('Dog')
            })
        },
        { 
            id: 3,
            data: new Promise((resolve, reject) => {
                resolve('Mouse')
            })
        }
    ]    
    
    Promise.map(list, Promise.props)
    .then(results => {
        console.log(results);
    });

    【讨论】:

    • {...item, data} 不错
    • 为了公平对待蓝鸟,Promise.map(list, Promise.props)(在隐藏的 sn-p 中)也有点甜(写了我自己的 Promise.mapPromise.probs 版本我终于找到了一个用途他们:p)
    【解决方案6】:

    将 Promise.all() 解析为一个实际可用的 JSON 数组。

    问题:Promise.all() 解析为一组已解析的 promise。要了解这是一个问题的原因,请将其复制并粘贴到您的控制台中:

    var promise1 = fetch('https://swapi.dev/api/people/2'); // C-3PO
    var promise2 = fetch('https://swapi.dev/api/people/3'); // R2-D2
    
    Promise.all([promise1, promise2])
        .then(res => console.log(res)); // resolved promises - trash...
    

    看看那些已解决的承诺中没有实际可用的数据..?在 Web 上,您需要调用另一个 Promise 将它们转换为文本或 html,或者最有可能是心爱的 json。但是如何才能有效地做到这一点呢?

    那么,我们的 Promise.all() 问题的解决方案是……更多 Promise.all()!!!

    例子:

    var promise3 = fetch('https://swapi.dev/api/people/1'); // Luke
    var promise4 = fetch('https://swapi.dev/api/people/4'); // Luke's daddy
    
    Promise.all([promise3, promise4])
        .then(res => Promise.all([res[0].json(), res[1].json()]))
        .then(res => console.log(res)); // real data :)
    

    希望这对某人有所帮助!谢谢!

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 2017-03-31
      • 1970-01-01
      • 2015-05-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      相关资源
      最近更新 更多