英文:
Confusion with .then() chaining
问题
我一直在尝试理解 Promises/then-ables 如何工作。
我正在使用 NextJS。
尝试链式操作以执行以下操作:
- 从API获取数据
 - 保存数据
 - 修改数据以创建组件
(并且不产生无限循环) 
我无法获取适当的数据来执行步骤#3。
我尝试了各种方法,但卡在这一步。
我正在使用 useEffect,因为这样做(尽管我确信还有其他方法可以实现):
https://nextjs.org/docs/basic-features/data-fetching/client-side
export default function Survey() {
  const [dataDB, setDataDB] = useState('');
  let roles = [];
  function createCards(rolesArr) {
    let role1 = tabs.find(x => x.id == rolesArr[0])
    let role2 = tabs.find(x => x.id == rolesArr[1])
    let role3 = tabs.find(x => x.id == rolesArr[2])
    // 上面的是空的
    // 下面的也是空的:
    //     let role1 = tabs.find(x => x.id == dataDB[0])
    roles.push(role1)
    roles.push(role2); 
    roles.push(role3); // 组件将遍历这3个
  }
  useEffect(() => {
    fetch('example.com/api')
      .then((response) => response.json()) // 1. 获取像[0, 3, 5]这样的数组
      .then((data) => {
        setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
      }
     .then((rolesArr) => createCards(rolesArr)) // 3. 修改数据以供组件使用
    })
  )  
  return ( 
    { 
      roles.map((path) => (
        <Card key={path.id}>
          <Text>{path.title}</Text>
        </Card>
      ))
    } 
  )
}
英文:
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:
- Get data from API
 - Save the data
 - 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
export default function Survey() {
  const [dataDB, setDataDB] = useState('');
  let roles;
  function createCards(rolesArr) {
    let role1 = tabs.find(x => x.id == rolesArr[0])
    let role2 = tabs.find(x => x.id == rolesArr[1])
    let role3 = tabs.find(x => x.id == rolesArr[2])
    // the above is null
    // the below is also null:
    //     let role1 = tabs.find(x => x.id == dataDB[0])
    roles.push(role1)
    roles.push(role2); 
    roles.push(role3); // component will map over these 3
  }
  useEffect(() => {
    fetch('example.com/api')
      .then((response) => response.json()) // 1. Gets an array like [0, 3, 5]
      .then((data) => {
        setData(dataDB) // 2. Using hook to setData, will store in database later
      }
     .then((rolesArr) => createCards(rolesArr)) // 3. Modify data for component
    })
  )  
  return ( 
    { 
      roles.map((path) => (
        <Card key={path.id}>
          <Text>{path.title}</Text>
        </Card>
      ))
    } 
  )
}
答案1
得分: 1
你在这里有很多问题。
roles 未定义
let roles; 创建了一个变量并将其值设置为 undefined。
下一次你使用它(这里:roles.map((path) => (),你尝试将其视为数组。
这将导致错误。
你需要在定义时将其设置为一个数组。
拼写错误
>     .then((data) => {
>             setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
>           }
你漏掉了一个 )。
rolesArr 是 undefined
以下代码块的返回值:
>     .then((data) => {
>             setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
>           }
… 是 undefined,因为你没有 return 语句,所以链中的下一个 then() 回调将接收到 undefined。
然而 你没有做任何需要你创建新的 Promise 的事情,所以没有必要使用额外的 then,只需在你已有的函数中完成所有你想要处理数据的工作。
  .then((data) => {
    setData(dataDB);
    createCards(dataDB);
  });
createCards 修改一个不存在且没有被任何地方使用的数组
>      roles.push(role1)
>      roles.push(role2);
>      roles.push(role3); // 组件将遍历这 3 个
你在这里有与之前相同的问题;roles 不是一个数组,它是 undefined。
而且,由于 createCards 是异步调用的,这段代码将在 roles.map((path) => ( 之后运行,所以没有东西会关注这个修改。
不要修改不存在的数组。创建一个新的数组并将其存储在状态中。设置状态将触发重新渲染,所以组件将从状态存储中提取数组并有一些值进行迭代。
通常你会想要做类似于:
const [roles, setRoles] = useState(null);
function createCards(rolesArr) {
    // 等等
    setRoles([role1, role2, role3]);
}
// 等等
如果 `roles` 为 `null`,则返回 <p>Loading</p>;
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) => () 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.
  .then((data) => {
    setData(dataDB);
    createCards(dataDB);
  });
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) => ( 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:
const [roles, setRoles] = useState(null);
function createCards(rolesArr) {
    // etc
    setRoles([role1, role2, role3]);
}
// etc
if (roles === null) {
    return <p>Loading</p>;
}
return roles.map(etc etc);
答案2
得分: 0
使用.then()时,如果要链式使用一个或多个.then(),需要从前一个回调函数返回生成的值。例如:
fetchData()
  .then((response) => {
    console.log(response.json())
    return response.json()
  }).then((values) => {
    console.log(values)
    return values.filter((value) => value > 0)
  }).then((positiveValues) => {
    console.log(positiveValues)
    return positiveValues;
  })
这个示例将打印response.json()并将其作为值返回,以便在下一个.then()回调中使用。
对于您的情况,可以像这样在第二个回调中返回值:
fetch('example.com/api')
  .then((response) => response.json()) // 1. 获取一个类似 [0, 3, 5] 的数组
  .then((data) => {
    setData(dataDB) // 2. 使用 hook 来设置数据,稍后将存储到数据库中
    return dataDB;
  }).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:
fetchData()
  .then((response) => {
    console.log(response.json())
    return response.json()
  }).then((values) => {
    console.log(values)
    return values.filter((value) => value > 0)
  }).then((positiveValues) => {
    console.log(positiveValues)
    return positiveValues;
  })
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:
    fetch('example.com/api')
      .then((response) => response.json()) // 1. Gets an array like [0, 3, 5]
      .then((data) => {
        setData(dataDB) // 2. Using hook to setData, will store in database later
        return dataDB;
      }).then((rolesArr) => createCards(rolesArr)) // 3. Modify data for component
    })
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论