Promise.all 的对象字面量(散列)
Object literal (hash) with 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 all 将适用于任何可迭代对象。据我所知,对象文字 {}
是可迭代的。那我错过了什么?
Syntax
Promise.all(iterable);
Parameters
iterable
An iterable object, such as an Array. See iterable.
如果您查看 mdn documentation 对象没有 Iterator 符号。
你可以做的是使用工具函数创建一个可迭代的对象,然后使用它。
reference to objectEntries source,但是 nodejs 没有实现 Reflect,所以为了在 node 中使用它,我只是将其更改为使用 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 };
}
}
};
}
默认情况下并非所有对象都是可迭代的。您可以通过定义 @@iterator
方法使对象可迭代。 @@iterator
是一个 Well-Known Symbol 可用 Symbol.iterator
:
- Specification Name
@@iterator
- [[Description]]
"Symbol.iterator"
- Value and Purpose
A method that returns the default Iterator for an object. Called by the semantics of the for-of statement.
例如,这将使所有对象都可迭代(可能不是一个好主意):
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 ]
});
使用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>
对于 Babel/ES2015,您可以使用 Object.keys 和映射来获取这样的值:
const obj = {a:1,b:2};
const vals = Object.keys(obj).map(k=>obj[k]);
Promise.all(vals).then( vals => { console.log('vals', vals) });
这个函数可以解决问题:
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;
});
};
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;
};
这是另一个异步/等待 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}), {});
}
这会将键转换为生成单个元素哈希的承诺。然后最后我们将数组中的所有散列组合成一个散列。您甚至可以将其压缩为一行,但要以可读性为代价。
async function allOfOneLiner(hash = {}) {
return (await Promise.all(Object.keys(hash).map(async k => ({[k]: await hash[k]})))).reduce((h, p) => ({...h, ...p}), {});
}
我遇到这样一种情况,使用 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 all 将适用于任何可迭代对象。据我所知,对象文字 {}
是可迭代的。那我错过了什么?
Syntax
Promise.all(iterable);
Parameters
iterable
An iterable object, such as an Array. See iterable.
如果您查看 mdn documentation 对象没有 Iterator 符号。
你可以做的是使用工具函数创建一个可迭代的对象,然后使用它。
reference to objectEntries source,但是 nodejs 没有实现 Reflect,所以为了在 node 中使用它,我只是将其更改为使用 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 };
}
}
};
}
默认情况下并非所有对象都是可迭代的。您可以通过定义 @@iterator
方法使对象可迭代。 @@iterator
是一个 Well-Known Symbol 可用 Symbol.iterator
:
- Specification Name
@@iterator- [[Description]]
"Symbol.iterator"- Value and Purpose
A method that returns the default Iterator for an object. Called by the semantics of the for-of statement.
例如,这将使所有对象都可迭代(可能不是一个好主意):
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 ]
});
使用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>
对于 Babel/ES2015,您可以使用 Object.keys 和映射来获取这样的值:
const obj = {a:1,b:2};
const vals = Object.keys(obj).map(k=>obj[k]);
Promise.all(vals).then( vals => { console.log('vals', vals) });
这个函数可以解决问题:
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;
});
};
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;
};
这是另一个异步/等待 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}), {});
}
这会将键转换为生成单个元素哈希的承诺。然后最后我们将数组中的所有散列组合成一个散列。您甚至可以将其压缩为一行,但要以可读性为代价。
async function allOfOneLiner(hash = {}) {
return (await Promise.all(Object.keys(hash).map(async k => ({[k]: await hash[k]})))).reduce((h, p) => ({...h, ...p}), {});
}