2016-03-07 107 views
7

的對象字面量(哈希值)我有一種情況,使用Promise.all(如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的對象字面的值映射,但將鑰匙保持原樣。)

the MDN docs for Promise似乎表明Promise都將適用於任何迭代。據我所知,一個對象文字{}是一個可迭代的。那麼我錯過了什麼?

+3

不,'{}'是不是一個迭代。 – 2016-03-07 01:19:41

+0

從這些文檔中我們不清楚{}是否是一個可迭代的,但它似乎是https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols –

+0

@AlexMills不確定爲什麼你認爲它不清楚。您鏈接的MDN文章解釋了「*某些內置類型是內置迭代,具有默認迭代行爲,如Array或Map,而其他類型(如Object)不是*」。 – Oriol

回答

3

如果您查看mdn documentation,則對象不具有迭代器符號。

你可以做什麼,是使用工具函數來創建一個可迭代的對象,然後消耗它。

reference to objectEntries source,但是沒有的NodeJS沒有實現反映,所以使用它與節點的目的,我只是把它變成使用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
Syntax 
Promise.all(iterable); 
Parameters 

迭代

一種迭代的對象,諸如數組。請參閱iterable。

+0

我不確定,請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols –

0

並非所有對象都默認迭代。您可以通過定義@@iterator方法來使對象可迭代。 @@iteratorWell-Known Symbol可作爲Symbol.iterator

  • 規格名稱
    @@迭代
  • [[說明]]
    「Symbol.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 ] 
}); 
+0

爲什麼downvote? – Oriol

+0

是不是我,我upvoted –

+0

有沒有一種方法來修改這個很容易,以便'then'回調傳遞給我們一個對象/散列與原來的鍵匹配的值而不是數組? –

3

使用Object.values。在Firefox每晚:

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>

+1

這個解決方案的問題是,結果數組中的元素的順序取決於值的順序由'Object.values'返回的數組,這可能不是你想要的東西。 – 2016-03-07 04:32:22

+0

@torazaburo當然,但這個問題是固有的問題。 – jib

+1

不是。您應該返回承諾結果的散列,如RSVP所做的那樣。 – 2016-03-07 05:28:20

0

隨着通過Babel/ES2015你可以使用Object.keys和map來得到像th這樣的值是:

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

我懷疑OP會希望返回一個帶有承諾的散列作爲密鑰的值。 – 2016-03-07 04:31:24

+1

您的懷疑是正確的:) –

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; 
    }); 
};