似乎无法返回值,仅能返回一个 Promise。

3

我正在尝试编写我的第一个React Native应用程序,所以它并不复杂,只是为了熟悉它的一些特性。现在它有一个按钮,当我按下它时,文本字段会增加1,我还希望该按钮显示另一个我已导入的函数中的一些文本。

我有我的主要App.js和另一个文件,我将其导入到App.js中,其中包含返回字符串值的函数。

import { myFunction } from './JSFunctions/functions.js'

我的函数在单独运行时能够正常工作,并通过console.log将结果打印到控制台,但是当我添加以下代码行时:
return output

我得到的全部都是

Promise { <pending> }

我意识到我需要使用await.then来转换promise,但我已经在桌子上敲了几个小时的头,试图让它工作,但我只是得到错误。

以下是函数:

export async function myFunction(){
\\lots of other code here that has been removed 
    var i;
    var output;
    for (i = 0; i < length; i++) { 
        output = DO STUFF AND CREATE A LONG STRING HERE
        console.log(output) //produces the correct output to console
    }
    return output;     
}

以下是 App.js 中的函数

export default class App extends React.Component {

  constructor(props) {
    super(props)
    this.state = { 
      count: 0, 
      output_string: ''
    }
  }

  onPress = () => {
    this.setState({
      count: this.state.count+1,
      output_string: myFunction()
    })

  }  


  render(){ 
    const handlePress = () => false
    return (
    <React.Fragment>
      <View style = {styles.container}>
        <TouchableOpacity
          onPress={this.onPress}
        >
          <Text>
            My First Button
          </Text>
        </TouchableOpacity>

        <Text>Hello World! This is a text area.</Text>
        <Text>{ this.state.count !== 0 ? this.state.count: null}</Text>
        <Text>{this.state.output_string}</Text>
      </View>
    </React.Fragment>
    );
  }

}
3个回答

2
我最近问过类似的问题,基本上原因是myFunction是一个async函数,因此它只会返回一个Promise
你有两个选择,要么链接一个.then,要么将你的onPress方法变成一个async方法。

onPress = async () => {
    this.setState({
      count: this.state.count+1,
      output_string: await myFunction()
    })

  } 


嗯,刚看到这个问题。将整个onPress函数设置为异步函数是否有任何好处,还是通常会过度设计? - zoonosis
据我所知,async/await关键字被引入来替代.then。原因是.then仍然采用嵌套回调的形式,可能会导致回调地狱,你可以将我的答案与被接受的答案进行比较,哪一个更容易理解?不过这当然是相对而言的。 - Isaac
"async/await" 只是对 "Promises" 和生成器的语法糖。本质上,"await" 调用会将函数的其余部分排队在与 "await" 相关的 "Promise" 的 "then" 回调中(这有点复杂,但这是一种容易理解发生了什么的方式)。因此,最终两种方法的行为非常相似,任何一种都可以正常工作。 - Brian Adams
@brian-lives-outdoors:这正是我所解释的,我的观点是使用async/await可以提高可读性,我也提到这是相当主观的 :) - Isaac
1
@Isaac 不用担心,我在我的答案中添加了一个 async 版本,并且我会点赞你的回答,因为你是第一个介绍 async 方法的人。 - Brian Adams

1
在返回自myFunctionPromise中链接then回调函数来设置状态:
onPress = () => {
  myFunction().then(output => {
    this.setState({
      count: this.state.count+1,
      output_string: output
    });
  })
}

更新
你也可以使用 async / await 语法:
onPress = async () => {
  const output = await myFunction();
  this.setState({
    count: this.state.count+1,
    output_string: output
  });
}

更新

OP询问是否可以独立更新countoutput_string。以下是使用async/await的示例:

onPress = async () => {
  this.setState({ count: this.state.count + 1 });  // This happens immediately
  this.setState({
    output_string: await myFunction()
  });  // This happens as soon as the Promise returned by myFunction resolves
}

谢谢,这个可行。请问,count:this.state.count+1 这一行需要在 then 回调函数内吗?数字计数器似乎在输出字符串被计算之前等待返回。或者这是不可避免的吗? - zoonosis
@zoonosis这取决于您是否需要同时更新countoutput_string。如果它们可以相互独立地更新,那么是的,您可以将设置count移动到回调之外。 - Brian Adams
我说你的async/await语法答案唯一的缺点是count和output_string将同时计算,这样说对吗?有没有办法使用这种方法但仍然将count单独计算? - zoonosis
1
@zoonosis,你可以使用任何一种方法独立更新countoutput_string。我已经添加了一个使用async/await分别更新的示例。 - Brian Adams

0

myFunction中删除await关键字。

目前,您正在表明该函数是异步的(因此有async关键字),这意味着它可能不会立即解析值。

因此,返回一个promise,它承诺在某个时间点返回一个值。

我强烈建议阅读有关async/await的文章。

编辑:或者,如果您希望函数保持异步,则可以使用@brian-lives-outdoors的建议。


是的,这个函数需要异步执行,因为它在输出之前还有其他的操作,我已经将其删除了。 - zoonosis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接