混淆了`.then()`链。

huangapple go评论113阅读模式
英文:

Confusion with .then() chaining

问题

我一直在尝试理解 Promises/then-ables 如何工作。
我正在使用 NextJS。

尝试链式操作以执行以下操作:

  1. 从API获取数据
  2. 保存数据
  3. 修改数据以创建组件
    (并且不产生无限循环)

我无法获取适当的数据来执行步骤#3。
我尝试了各种方法,但卡在这一步。

我正在使用 useEffect,因为这样做(尽管我确信还有其他方法可以实现):
https://nextjs.org/docs/basic-features/data-fetching/client-side

  1. export default function Survey() {
  2. const [dataDB, setDataDB] = useState('');
  3. let roles = [];
  4. function createCards(rolesArr) {
  5. let role1 = tabs.find(x => x.id == rolesArr[0])
  6. let role2 = tabs.find(x => x.id == rolesArr[1])
  7. let role3 = tabs.find(x => x.id == rolesArr[2])
  8. // 上面的是空的
  9. // 下面的也是空的:
  10. // let role1 = tabs.find(x => x.id == dataDB[0])
  11. roles.push(role1)
  12. roles.push(role2);
  13. roles.push(role3); // 组件将遍历这3个
  14. }
  15. useEffect(() => {
  16. fetch('example.com/api')
  17. .then((response) => response.json()) // 1. 获取像[0, 3, 5]这样的数组
  18. .then((data) => {
  19. setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
  20. }
  21. .then((rolesArr) => createCards(rolesArr)) // 3. 修改数据以供组件使用
  22. })
  23. )
  24. return (
  25. {
  26. roles.map((path) => (
  27. <Card key={path.id}>
  28. <Text>{path.title}</Text>
  29. </Card>
  30. ))
  31. }
  32. )
  33. }
英文:

I've been trying to understand how Promises/then-ables work for awhile now.
I'm working with NextJS.

Trying to chain together to do the following:

  1. Get data from API
  2. Save the data
  3. Modify the data to create component
    (And not infinite loop)

I can't get the proper data to do step #3.
I've tried various things but am stuck on this step.

I'm using useEffect because of this (though I'm sure there's other ways to do it):
https://nextjs.org/docs/basic-features/data-fetching/client-side

  1. export default function Survey() {
  2. const [dataDB, setDataDB] = useState(&#39;&#39;);
  3. let roles;
  4. function createCards(rolesArr) {
  5. let role1 = tabs.find(x =&gt; x.id == rolesArr[0])
  6. let role2 = tabs.find(x =&gt; x.id == rolesArr[1])
  7. let role3 = tabs.find(x =&gt; x.id == rolesArr[2])
  8. // the above is null
  9. // the below is also null:
  10. // let role1 = tabs.find(x =&gt; x.id == dataDB[0])
  11. roles.push(role1)
  12. roles.push(role2);
  13. roles.push(role3); // component will map over these 3
  14. }
  15. useEffect(() =&gt; {
  16. fetch(&#39;example.com/api&#39;)
  17. .then((response) =&gt; response.json()) // 1. Gets an array like [0, 3, 5]
  18. .then((data) =&gt; {
  19. setData(dataDB) // 2. Using hook to setData, will store in database later
  20. }
  21. .then((rolesArr) =&gt; createCards(rolesArr)) // 3. Modify data for component
  22. })
  23. )
  24. return (
  25. {
  26. roles.map((path) =&gt; (
  27. &lt;Card key={path.id}&gt;
  28. &lt;Text&gt;{path.title}&lt;/Text&gt;
  29. &lt;/Card&gt;
  30. ))
  31. }
  32. )
  33. }

答案1

得分: 1

你在这里有很多问题。

roles 未定义

let roles; 创建了一个变量并将其值设置为 undefined

下一次你使用它(这里:roles.map((path) => (),你尝试将其视为数组。

这将导致错误。

你需要在定义时将其设置为一个数组。

拼写错误

> .then((data) => {
> setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
> }

你漏掉了一个 )

rolesArrundefined

以下代码块的返回值:

> .then((data) => {
> setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
> }

… 是 undefined,因为你没有 return 语句,所以链中的下一个 then() 回调将接收到 undefined

然而 你没有做任何需要你创建新的 Promise 的事情,所以没有必要使用额外的 then,只需在你已有的函数中完成所有你想要处理数据的工作。

  1. .then((data) => {
  2. setData(dataDB);
  3. createCards(dataDB);
  4. });

createCards 修改一个不存在且没有被任何地方使用的数组

> roles.push(role1)
> roles.push(role2);
> roles.push(role3); // 组件将遍历这 3 个

你在这里有与之前相同的问题;roles 不是一个数组,它是 undefined

而且,由于 createCards 是异步调用的,这段代码将在 roles.map((path) => ( 之后运行,所以没有东西会关注这个修改。

不要修改不存在的数组。创建一个新的数组并将其存储在状态中。设置状态将触发重新渲染,所以组件将从状态存储中提取数组并有一些值进行迭代。

通常你会想要做类似于:

  1. const [roles, setRoles] = useState(null);
  2. function createCards(rolesArr) {
  3. // 等等
  4. setRoles([role1, role2, role3]);
  5. }
  6. // 等等
  7. 如果 `roles` `null`,则返回 <p>Loading</p>;
  8. return roles.map(等等等等);
英文:

You have a lot of problems here.

roles is undefined

let roles; creates a variable and sets its value to undefined.

The next time you touch it (here: roles.map((path) =&gt; () you are trying to treat it as an array.

This will error.

You need to make it an array when you define it.

a typo

> .then((data) => {
> setData(dataDB) // 2. Using hook to setData, will store in database later
> }

You are missing a ) from the end of there

rolesArr is undefined

The return value of:

> .then((data) => {
> setData(dataDB) // 2. Using hook to setData, will store in database later
> }

… is undefined because you have no return statement, so the next then() callback in the chain gets passed undefined.

However you aren't doing anything that requires you to create a new promise there, so there's no point in using an extra then, just do everything you want to do with the data in the function you already have.

  1. .then((data) =&gt; {
  2. setData(dataDB);
  3. createCards(dataDB);
  4. });

createCards modifies an array that doesn't exist and that nothing uses

> roles.push(role1)
> roles.push(role2);
> roles.push(role3); // component will map over these 3

You have the same problem here that you did earlier; roles isn't an array, it is undefined.

What's more, because createCards is called asynchronously, this code will run after roles.map((path) =&gt; ( so nothing is going to pay attention to the mutation anyway.

Don't mutate the non-existent array. Create a new one and store it in a state. Setting a state will trigger a re-render so the component will pull the array out of the state storage and have some values to iterate over.

Typically you would want to do something like:

  1. const [roles, setRoles] = useState(null);
  2. function createCards(rolesArr) {
  3. // etc
  4. setRoles([role1, role2, role3]);
  5. }
  6. // etc
  7. if (roles === null) {
  8. return &lt;p&gt;Loading&lt;/p&gt;;
  9. }
  10. return roles.map(etc etc);

答案2

得分: 0

使用.then()时,如果要链式使用一个或多个.then(),需要从前一个回调函数返回生成的值。例如:

  1. fetchData()
  2. .then((response) => {
  3. console.log(response.json())
  4. return response.json()
  5. }).then((values) => {
  6. console.log(values)
  7. return values.filter((value) => value > 0)
  8. }).then((positiveValues) => {
  9. console.log(positiveValues)
  10. return positiveValues;
  11. })

这个示例将打印response.json()并将其作为值返回,以便在下一个.then()回调中使用。

对于您的情况,可以像这样在第二个回调中返回值:

  1. fetch('example.com/api')
  2. .then((response) => response.json()) // 1. 获取一个类似 [0, 3, 5] 的数组
  3. .then((data) => {
  4. setData(dataDB) // 2. 使用 hook 来设置数据,稍后将存储到数据库中
  5. return dataDB;
  6. }).then((rolesArr) => createCards(rolesArr)) // 3. 修改组件的数据
英文:

When using the .then(), you need to return the resulting value from the previous callback function if you want to chain one or more .then(). As an example:

  1. fetchData()
  2. .then((response) =&gt; {
  3. console.log(response.json())
  4. return response.json()
  5. }).then((values) =&gt; {
  6. console.log(values)
  7. return values.filter((value) =&gt; value &gt; 0)
  8. }).then((positiveValues) =&gt; {
  9. console.log(positiveValues)
  10. return positiveValues;
  11. })

This example will print the response.json() and return it as a value to be used as an argument on the next .then() callback.

For your case, return the value inside the second callback like this:

  1. fetch(&#39;example.com/api&#39;)
  2. .then((response) =&gt; response.json()) // 1. Gets an array like [0, 3, 5]
  3. .then((data) =&gt; {
  4. setData(dataDB) // 2. Using hook to setData, will store in database later
  5. return dataDB;
  6. }).then((rolesArr) =&gt; createCards(rolesArr)) // 3. Modify data for component
  7. })

huangapple
  • 本文由 发表于 2023年3月7日 04:02:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655331.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定