使用Promise.all的对象文字(哈希)

时间:2016-03-07 00:55:09

标签: javascript node.js ecmascript-6 es6-promise

我的情况是使用Promise.all这样Promise.all({})代替更标准的Promise.all([])会非常方便。

但这似乎不起作用

Promise.all({a:1,b:2}).then(function(val){
   console.log('val:',val);
});

虽然这当然是

Promise.all([1,2,3]).then(function(val){
   console.log('val:',val);
});

(我期望Promise.all能够映射Object文字的值,但保持密钥完整。)

但是the MDN docs for Promise似乎表明Promise all适用于任何迭代。据我所知,对象文字{}是可迭代的。那我错过了什么?

8 个答案:

答案 0 :(得分:3)

如果您查看mdn documentation,那么对象没有迭代器符号。

你可以做的是使用工具函数来创建一个可迭代的对象,然后再使用它。

reference to objectEntries source,但是nodejs没有实现Reflect,所以为了将它与节点I一起使用,只需将其更改为使用Object.keys()

function objectEntries(obj) {
    let index = 0;

    // In ES6, you can use strings or symbols as property keys,
    // Reflect.ownKeys() retrieves both
    let propKeys = Object.keys(obj);

    return {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (index < propKeys.length) {
                let key = propKeys[index];
                index++;
                return { value: [key, obj[key]] };
            } else {
                return { done: true };
            }
        }
    };
}

答案 1 :(得分:3)

使用Object.values。适用于Firefox Nightly:

Promise.all(Object.values({a:1,b:2}))
.then(vals => console.log('vals: ' + vals)) // vals: 1,2
.catch(e => console.log(e));

var console = { log: msg => div.innerHTML += msg + "<br>" };
<div id="div"></div>

然后,为了将结果放回到对象中,我们可以创建一个Promise.allParams函数:

Promise.allParams = o => 
  Promise.all(Object.values(o)).then(promises =>
    Object.keys(o).reduce((o2, key, i) => (o2[key] = promises[i], o2), {}));

// Demo:

Promise.allParams({a:1,b:2}).then(function(val){
   console.log('val: ' + JSON.stringify(val)); // val: {"a":1,"b":2}
});

var console = { log: msg => div.innerHTML += msg + "<br>" };
<div id="div"></div>

答案 2 :(得分:1)

Syntax
Promise.all(iterable);
Parameters
  

迭代

     

可迭代对象,例如Array。见iterable。

答案 3 :(得分:1)

这是另一个异步/等待ES6解决方案:

async function allOf(hash = {}) {
  const promises = Object.keys(hash).map(async key => ({[key]: await hash[key]}));
  const resolved = await Promise.all(promises);
  return resolved.reduce((hash, part) => ({...hash, ...part}), {});
}

这会将密钥转换为产生单个元素哈希的Promise。然后最后,我们将数组中的所有哈希组合到单个哈希中。您甚至可以将其压缩为一个单一的行,以牺牲可读性为代价。

async function allOfOneLiner(hash = {}) {
  return (await Promise.all(Object.keys(hash).map(async k => ({[k]: await hash[k]})))).reduce((h, p) => ({...h, ...p}), {});
}

答案 4 :(得分:0)

默认情况下,并非所有对象都是可迭代的。您可以通过定义@@iterator方法使对象可迭代。 @@iteratorWell-Known SymbolSymbol.iterator

  
      
  • 规格名称
      @@迭代
  •   
  • [[说明]]
      &#34; Symbol.iterator&#34;
  •   
  • 价值和目的
      返回对象的默认Iterator的方法。由for-of语句的语义调用。
  •   

例如,这将使所有对象可迭代(可能不是一个好主意):

Object.prototype[Symbol.iterator] = function*() {
  for(let key of Object.keys(this))
    yield this[key];
};

然后你就可以使用

Promise.all({a:1,b:2}).then(function(val){
   console.log('val:', val); // [ 1, 2 ]
});

答案 5 :(得分:0)

使用Babel / ES2015,您可以使用Object.keys和map来获取如下值:

const obj = {a:1,b:2};                                                                                                                               
const vals = Object.keys(obj).map(k=>obj[k]);                                                                                                        
Promise.all(vals).then( vals => { console.log('vals', vals) });                         

答案 6 :(得分:0)

这个功能可以解决问题:

Promise.allAssoc = function(object){
    var values = [], keys = [];
    for(var key in object){
        values.push(object[key]);
        keys.push(key);
    }
    return Promise.all(values).then(function(results){
        var out = {};
        for(var i=0; i<results.length; i++) out[keys[i]] = results[i];
        return out;
    });
};

答案 7 :(得分:0)

ES6方式

Promise.hashProperties = async function(object) {
    const keys = [];
    const values = [];

    for (const key in object) {
        keys.push(key);
        values.push(object[key]);
    }

    const results = await Promise.all(values);

    for (var i=0; i<results.length; i++)
        object[keys[i]] = results[i];

    return object;
};