编辑:
我希望我的updateInventory
函数返回一个具有每个promise属性的对象。
我既不知道将使用哪个命令,也不知道命令的顺序
问题是t.batch
和Promise.all
返回一个索引数组,因此我无法将Promise与它的组件关联以输出所需的对象。
受这个post的启发,我这样做了:
首先执行then
中的getStatement
来格式化每个Promise的结果数据:具有name
和data
属性的对象。
然后使用所有这些对象解析t.batch
。结果仍然是索引数组,但是每个对象都包含名称和数据。
这样我就可以创建我的最终对象。
也许有更好的方法吗?
以下示例: 我的输入:
{
device: {
deviceId: 1,
name: "myName",
istate: "updated"
},
system: {
systemId: 50,
domain: 'foo.fr',
istate: "updated"
},
ifaces: [
{
interfaceId: 75,
name: "Iface Update 1",
istate: "updated"
},
{
name: "New Interface 1",
istate: "added"
}
]
}
仅带有t.batch()
或`Promise.all()的“标准”输出:一个索引数组
[
0: { deviceId: 1 },
1: { systemId: 50 },
2: [
{ interfaceId: 75 },
{ interfaceId: 76 }
]
]
我的自定义t.batch
输出:
[
0: { name: "device", data: { deviceId: 1 }}
1: { name: "system", data: { systemId: 50 }}
2: { name: "ifaces", data: [{ interfaceId: 75 },{ interfaceId: 76 }] }
]
然后我可以构建我的最终对象(下面的values.forEach
):
{
"device": { deviceId: 1 },
"system": { systemId: 50 },
ifaces: [
{ interfaceId: 75 },
{ interfaceId: 76 }
]
}
代码(简体):
function updateInventory(params) {
const { /* hidden */, ...components } = params.data; // simplified
return Database.tx('Inventory-Update', t => { // postgres transaction with pg-promise library
const statements = []; // promise array
for(let [prop, component] of Object.entries(components)) {
statements.push(getStatement(t, prop, component));
}
return t.batch(statements);
}).then(results => {
let result = {};
results.forEach(res => {
result[res.name] = res.data;
});
return result;
});
}
function getStatement(t, prop, component) {
const repo = getReposName(prop);
const state = component.istate;
let statement;
switch(state) {
case "updated":
statement = t[repo].update(component);
break;
case "removed":
statement = t[repo].delete(component);
break;
default:
statement = t[repo].insert(component);
break;
}
return statement.then(res => {
return {name: prop, data: res };
});
}
答案 0 :(得分:1)
它基于Promises的工作方式。 then
表示承诺得到解决后,它将运行下一部分。但是,您可以将多个then
添加到单个承诺中,并且它们不会互相影响。
在此示例中,您可以看到Promise all在then
语句之前已解决(因为它只是等待语句完成,而不是waitABit部分)。
function getStatement() {
const statement = waitABit();
statement.then(res => {
let foo={name: Math.random(), data: [Math.random()] };
console.log(foo);
return foo;
});
return statement;
}
async function waitABit() {
return new Promise(resolve => setTimeout(resolve,1000));
}
async function callAll() {
statements = [];
for (let i=0; i < 3; i++){
statements.push(getStatement());
}
console.log(await Promise.all(statements));
}
callAll();
此部分易于修复:
function getStatement() {
let statement = waitABit();
const afterStatement = statement.then(res => {
let foo={name: Math.random(), data: [Math.random()] };
console.log(foo);
return foo;
});
return afterStatement;
}
async function waitABit() {
return new Promise(resolve => setTimeout(resolve,1000));
}
async function callAll() {
statements = [];
for (let i=0; i < 3; i++){
statements.push(getStatement());
}
console.log(await Promise.all(statements));
}
callAll();
但是在您的情况下,它也可能不是一个选择,因为在那之后,您将把将用nam
和data
来解决的承诺放到t.batch(statements);
中,这很可能会失败。 / p>
您需要以不同的方式进行处理-即getStatement将返回数据库中包含这些更新以及所需数据的数据结构,然后等到数据更新后再继续操作。
答案 1 :(得分:1)
您的期望是错误并且您获得的输出是正确的(承诺数组)
简单的例子:
function getPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("data"), 200)
})
}
function something() {
// codes ...
let res = getPromise()
res.then(d => {
// you're expecting this to be returned, but remember this runs in Future
// this part of execution happens after res is returned in the last line
console.log('this is executed after return')
return d;
})
return res; // <-- this is what is actually returned
}
console.log(something())
注意:由于某种原因,在Firefox中运行此代码段时,我只能看到{}
,而看不到Promise { <state>: "pending" }
,如果是这种情况,请打开浏览器以确认输出为Promise
>
解决方案?
也许吗?:
// get rid of statement.then...
return { name, data: statement };
答案 2 :(得分:1)
一个问题是 statement.then(res => {
let foo={name: name, data: res };
console.log(foo);
return foo;
});
return statement;
返回了一个新的承诺,因此您需要更改它:
return statement.then(res => {
let foo={name: name, data: res };
console.log(foo);
return foo;
});
对此:
.then()
您需要返回foo
返回的新承诺,因为这是将{{1}}作为已解决值的承诺。