链接时如何使用JS Promise?

问题描述

在下面的代码中,为什么我在最后一行得到一个未定义的?如何编写以获取变量a中的响应

function getData(){
const url = "https://jsonplaceholder.typicode.com/users";
url2='https://jsonplaceholder.typicode.com/posts/'
fetch(url).then((res) =>{
  res.json().then((dataAsJson) => {
    return(dataAsJson[0].id);
  })
  .then((id)=>{
     fetch(url2+"/"+id).then((res)=> {
     return res.json().then((data) => {
      return(data);
    })
    })
})

})
}


var a = getData();
console.log(a)```

解决方法

您缺少两个return语句,实际上将值从一个promise传递到下一个promise。因此,要使代码正常工作,您必须将它们包括在内:

async function getData(){
  const url = "https://jsonplaceholder.typicode.com/users";
  url2='https://jsonplaceholder.typicode.com/posts/'
  const data = await fetch(url).then((res) =>{
    return res.json().then((dataAsJson) => {
      return(dataAsJson[0].id);
    })
  .then((id)=>{
     return fetch(url2+"/"+id).then((res)=> {
        return res.json().then((data) => {
          return(data);
        })
      })
    })
  })
}

这里的另一个提示:从承诺中返回时,无论是其他承诺还是简单的值都没关系-下一个then调用将始终获取未包装的值。因此,您实际上不必嵌套所有这些promise调用。如果这样说,它将更容易阅读:

const url = "https://jsonplaceholder.typicode.com/users";
url2='https://jsonplaceholder.typicode.com/posts/'
const data = await fetch(url)
  .then((res) =>{ return res.json()})
  .then((dataAsJson) => { return(dataAsJson[0].id); })
  .then((id)=>{ return fetch(url2+"/"+id); })
  .then((res)=> { return res.json(); })

还有:由于您仅在每个回调中返回一个值,因此可以利用JavaScript-Arrow-Function功能,该功能会在只有一个表达式的情况下自动返回,并将其进一步缩短为该表达式:

const url = 'https://jsonplaceholder.typicode.com/users';
url2 = 'https://jsonplaceholder.typicode.com/posts/';
const data = await fetch(url)
  .then(res => res.json())
  .then(dataAsJson => dataAsJson[0].id)
  .then(id => fetch(`${url2}/${id}`))
  .then(res => res.json());

可读性更好,更容易发现错误。 :)

更新:我完全忽略了您的代码,您试图从异步getData()函数中同步读取。 @幽灵在他的回答中澄清了这一点-因此这应该被接受。但是,为了不让错误的代码站起来,我在答案中编辑了正确的行为。

,

您应该可以使用await来简化该功能。 它消除了对嵌套回调的需要。该代码未经测试,但理论上应该可以工作。

async function getData() {
  const url = "https://jsonplaceholder.typicode.com/users";
  const url2 = "https://jsonplaceholder.typicode.com/posts/";

  const firstFetch = await fetch(url)
  const firstResult = await firstFetch.json();

  const id = firstResult[0].id;

  const secondFetch = await fetch(url2 + "/" + id)
  return await secondFetch.json();
}

https://javascript.info/async-await

您也可以创建一个新的Promise,以在第二次获取时解决。但是这种方法比较麻烦

,

由于您没有从getData()返回任何内容,因此变得不确定。

Promises及其链接的方法then()catch会自己返回Promise的一个实例,而不是您从then()的回调中返回的数据。

要获得您期望的行为,一种方法是使用asyncawait。 David带大卫,您会这样做:

const url = 'https://jsonplaceholder.typicode.com/users';
const url2 = 'https://jsonplaceholder.typicode.com/posts/';
const data = await fetch(url)
  .then(res => res.json())
  .then(dataAsJson => dataAsJson[0].id)
  .then(id => fetch(`${url2}/${id}`))
  .then(res => res.json());
  
console.log(data);