我有一个诺言链,可以找到一个数组。我希望数组返回一些结果(将来可以在其中将其设置为状态变量)。但是,我只是兑现诺言。我想知道我在这里做错了什么。
现在,我正在控制台记录阵列中的项目,以查看其是否返回值,而不是Promise。
addIPFSItem = () => {
var finalItems = []
var searchAddress = "0x9Cf0dc46F259542A966032c01DD30B8D1c310e05";
const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
simpleStorage.setProvider(this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {
simpleStorage.deployed().then((instance) => {
this.simpleStorageInstance = instance
return this.simpleStorageInstance.getLength(searchAddress);
}).then((accountLength) => {
var movieItems = []
var i;
var indexCounter = 0;
//WITHIN THIS LOOP extend the chain to add to movies
for (i = 0; i < accountLength; i++) {
var p = this.simpleStorageInstance.getBook(searchAddress, i, { from: searchAddress }).then((hashVal) => {
return hashVal;
}).then((hashVal)=>{
var ipfsPrefix = "https://ipfs.io/ipfs/";
var ipfsURL = ipfsPrefix + hashVal;
return ipfsURL
})
var k = this.simpleStorageInstance.getTitle(searchAddress, i, { from: searchAddress }).then((title) => {
return title;
})
var l = this.simpleStorageInstance.getContents(searchAddress, i, { from: searchAddress }).then((contents) => {
return contents;
})
movieItems.push({id: i, poster_src: p, title: k, overview: l})
indexCounter++
console.log('counter: ', i, p, k, l)
}
//return items
return movieItems
}).then((array) =>{
var i
for(i=0; i<array.length; i++){
console.log('Array item: ', array[i])
}
return finalItems
})
})
}
我不知道在将var p
,var k
,var l
添加到movieItems
数组时是否需要链接它们。假设在我推到movieItems
之后,我可以尝试获取数组中的每个值,因为我已经正确检索了这些值?
答案 0 :(得分:2)
您正试图在这里欺骗诺言!
运行时
var l = this.simpleStorageInstance.getContents(searchAddress, i, { from: searchAddress }).then((contents) => {
console.log('Retrieved contents');
return contents;
});
movieItems.push({id: i, poster_src: p, title: k, overview: l});
console.log('Pushed!')
javascript引擎会说“我将这个承诺直接放入l
,然后继续进行movieItems.push
”。如果运行此命令,则会看到日志显示为
关于诺言有很多东西要学习,因此我无法在这篇文章中解释所有内容。假设您拥有支持该环境的环境或构建工具,现在的快速解决方案是使用async/await
。这样,您可以使javascript“等待”,直到您的诺言得以兑现。
首先您进行更改
}).then((accountLength) => {
至}).then(async (accountLength) => {
它告诉javascript您将使用await
并在函数内部使用Promises。然后,您可以像这样使用.then
来代替await
:
// Here I use `await` instead of `.then` to make the promise return "normally"
var hashVal = await this.simpleStorageInstance.getBook(searchAddress, i, { from: searchAddress });
// I do the transformations you did inside `.then(() => { ... })` "just" after the function call
var ipfsPrefix = "https://ipfs.io/ipfs/";
var ipfsURL = ipfsPrefix + hashVal;
var p = ipfsURL;
// Again, using `await` instead of `.then`
var k = await this.simpleStorageInstance.getTitle(searchAddress, i, { from: searchAddress })
var l = await this.simpleStorageInstance.getContents(searchAddress, i, { from: searchAddress });
这将使您的函数实际上返回一个值数组,而不是内部带有promise的数组。 希望这可以帮助! :)
答案 1 :(得分:0)
这是因为变量p
,k
和l
的值是 。他们将永远是诺言,因为这就是this.simpleStorageInstance.getBook()
等人的回报。向它们添加.then()
并不能使它们同步表示其值,它们仍然是Promises。您需要巧妙地编写Promises,以确保所需的值在您想要的时间和地点可用-我建议您更多地阅读它们的工作原理。
一个简单的解决方法可能是简单地使用await
。它基本上会暂停执行,直到异步Promise完成为止,并将确保p
,k
和l
代表您期望的值。 MDN documentation。
addIPFSItem = () => {
var finalItems = []
var searchAddress = "0x9Cf0dc46F259542A966032c01DD30B8D1c310e05";
const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
simpleStorage.setProvider(this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {
simpleStorage.deployed().then((instance) => {
this.simpleStorageInstance = instance
return this.simpleStorageInstance.getLength(searchAddress);
}).then((accountLength) => {
var movieItems = []
var i;
var indexCounter = 0;
//WITHIN THIS LOOP extend the chain to add to movies
for (i = 0; i < accountLength; i++) {
let p = await this.simpleStorageInstance.getBook(searchAddress, i, { from: searchAddress }).then((hashVal) => {
return hashVal;
}).then((hashVal) => {
var ipfsPrefix = "https://ipfs.io/ipfs/";
var ipfsURL = ipfsPrefix + hashVal;
return ipfsURL
});
let k = await this.simpleStorageInstance.getTitle(searchAddress, i, { from: searchAddress });
let l = await this.simpleStorageInstance.getContents(searchAddress, i, { from: searchAddress });
movieItems.push({ id: i, poster_src: p, title: k, overview: l })
indexCounter++
console.log('counter: ', i, p, k, l)
}
//return items
return movieItems
}).then((array) => {
var i
for (i = 0; i < array.length; i++) {
console.log('Array item: ', array[i])
}
return finalItems
})
})
}
P.S。如果您使用的是const
,则应该使用let
而不是var
。基本上没有理由在ES6中使用var
。