【发布时间】:2018-02-01 08:37:18
【问题描述】:
我正在使用 Web3.js 调查各种以太坊智能合约的价格。这是异步完成的,很多时候返回的值是乱序的,这意味着它们以错误的顺序被推送到新数组中。我想将值推送到 forEach 循环内的新数组,以便我可以使用 jQuery 更新页面上的值。保持秩序井然的最佳方法是什么?
采取的步骤:
首先我将所有的合约按顺序拼接成一个数组。
var Contracts = [];
Contract.splice(0, 0, EthereumContract.at("0x2a50fb3396455717043ae5aa631d362c94fe13e1"));
Contract.splice(1, 0, EthereumContract.at("0x69ec0658ff334789c7f57edc3a2f28adef1c0ef3"));
Contract.splice(2, 0, EthereumContract.at("0x4d2bab147c32c75c8c9277182e64c69e14cb9f3c"));
Contract.splice(3, 0, EthereumContract.at("0xcd56f2c89128ad71cfd87b0fc78c9e26990b0f66"));
然后我创建一个新数组“TheCurrentPrice”,它应该接收每份合约的价格。
var TheCurrentPrice = [];
现在我按顺序遍历数组并将 Price 方法应用于数组中的合约。我将返回的结果推送到一个新数组中。不幸的是,它有时会出现乱序响应并被错误地推送到新数组中。
Contract.forEach(function (Contract) {
Contract.Price(function (error, result) {
TheCurrentPrice.push(result);
});
});
解决方案:
Alnitak 给出了正确的答案,但语法不正确,以防将来有人尝试这样做。
function PricePromise(Contract) {
return new Promise((resolve, reject) => {
Contract.Price(function (error, result) {
if (error) {
reject(error);
console.log("Price Error");
} else {
resolve(result);
console.log("Price " + result);
}
});
});
};
Promise.all(Contract.map(PricePromise))
.then(function(Price) {
('#Product-Price-1').attr('data-price', Price[0] / 1000000000000000000);
/*This uses jQuery to update a custom data-* attribute in HTML5. Price[0] is of course the first entry in the array of prices retrieved with the promise.*/
...
});
我不太明白为什么 resolve(result) 允许我放弃 Price 方法的 forEach 循环,但您不需要 forEach,这是正确的语法。
【问题讨论】:
-
用增量 ID 标记请求并推送到数组的该索引。
arr[id] = result -
'Promise.all: Order of resolved values'线程我在问之前遇到过。这显然是答案的一部分,但 Alnitak 正确回答了特定用例。另一个线程更抽象,答案主要是行话,需要 ES6 之后的当前 JS 知识,这是最近的东西(三年前)。我还是说很酷很恶心。 :-)
标签: javascript arrays asynchronous foreach