异步承诺没有获得正确的价值

时间:2018-08-23 18:25:37

标签: javascript asynchronous promise

function getProjects() {
  return new Promise(function(resolve, reject) {

    axios.get('url', {
      auth: {
        username: 'username',
        password: '   '
      }
    }).then(function(response) {
      let res = response.data.value;
      for (let i = 0; i < res.length; i++) {
        projects.push(res[i])
        resolve(projects);
      }
      console.log(projects)
    }).catch(function(error) {
      console.log(error)
    })
  })
}

getProjects()
  .then(function(proj) {
    console.log('proj', proj)

    function asnycItemAssignment() {
      return new Promise(function(resolve, reject) {
        for (let i = 0; i < proj.length; i++) {
          axios.get(`url`, {
              auth: {
                username: 'username',
                password: '   '
              }
            }).then(function(response) {
              //console.log(response.data.value)
              finalArr.push(response.data.value)
            })
            .catch(function(error) {
              console.log(error)
            })
        }

        resolve(finalArr)
      })
    }

    asnycItemAssignment()
      .then(function(res) {

        console.log('res', res)

        function flatten() {
          return new Promise(function(resolve, reject) {

            var myNewArray3 = [];
            for (var i = 0; i < res.length; ++i) {
              for (var j = 0; j < res[i].length; ++j) {

                console.log('pushed', i, j, res[i][j])
                myNewArray3.push(res[i][j]);
              }
            }

            console.log('finalArr', myNewArray3)
            resolve(myNewArray3)
          })
        }

        flatten()
          .then(function(value) {
            console.log('val', value)
          })

      })

  })
}

这就是我想要做的。

我正在尝试从API提取项目列表,将其存储到projects并将其解析为Promise。再一次,我尝试使用projects的名称,并将其用于另一个API,该API向我提供该项目中的数据。这会将其存储到finalArr中。这次我解决了finalArr

finalArr是对象数组的数组。像[[{...}{...}][{...}]]这样的东西,这就是为什么我想变平使其像[{...},{...},{...},{...}]的原因。

但是,在我的asnycItemAssignment中,应该给我res结果的finalArr并没有给我完整的数组,其中包含所有值。

代码相当混乱,但是我觉得我做得正确。 我在做什么错了?

编辑

async function getData() {
  let getProject =
    await axios.get('url', {
      auth: {
        username: 'username',
        password: '    '
      }
    })

  let projects = await getProject.data.value;

  projects.map(project => {
    let ItemAssignment = 
      axios.get(`url`, {
        auth: {
          username: 'username',
          password: '    '
        }
      })

    let values = await ItemAssignment.data.value
    console.log(values)
  })

  console.log('pr', projects)
}

getData()

2 个答案:

答案 0 :(得分:2)

我真的认为您应该阅读异步/等待。当您依靠一个异步操作的结果执行另一个操作时,它使代码更具可读性。下面是一些伪代码,以使您入门:

async function go() {
    try {
        const projects = await getProjects();
        projects.map(project => {
            const itemAssignments = await asnycItemAssignment(project);
            const flattened = await flatten(itemAssignments);
            console.log(flattened);
        }
    } catch (e) {
        console.error(e); // 
    }
}

此外,通常还可以查看如何使用axios:

async getData() {
    return await axios(...);
}

然后您可以使用getData,例如:

const r = await GetData();

答案 1 :(得分:0)

您的代码存在以下问题:

  for (let i = 0; i < res.length; i++) {
    projects.push(res[i])
    resolve(projects)
  }

在for循环(或任何其他循环构造)中调用promise的resolve()方法几乎没有任何意义,因为您只能有意义地调用一次,或者更确切地说,promise只要得到解决即可您第一次打电话。实际上,此问题隐藏在代码中,因为您每次在for循环中循环就地修改projects时,for循环实际上可能已完成在您将已解决的承诺用于任何事情之前。

解决第一个问题就像将resolve(projects)下移几行一样简单:

  for (let i = 0; i < res.length; i++) {
    projects.push(res[i])
  }
  console.log(projects)
  resolve(projects)

不过,主要的问题可能是您何时以及如何在此处致电resolve(finalArr)

  return new Promise(function(resolve, reject) {
    for (let i = 0; i < proj.length; i++) {     
      axios.get(`url`, {                        
        auth: {                                 
          username: 'username',                 
          password: '   '                       
        }                                       
      }).then(function(response) {              
        //console.log(response.data.value)      
        finalArr.push(response.data.value)      
      })                                        
      .catch(function(error) {                  
        console.log(error)                      
      })                                        
    }                                           

    resolve(finalArr)                           
  })                                            

直到单个finalArr的呼叫解决后,才会发生向axios.get的推送,但是您对resolve(finalArr)的呼叫基本上(立即)立即发生axios.get呼叫已开始

解决这个问题比较棘手,因为您要等到所有axios.get调用完成后才能解决。一种方法是使用Promise.all()

function asnycItemAssignment() {
  for (let i = 0; i < proj.length; i++) {
    finalArr.push(
      axios.get(`url`, {
        auth: {
          username: 'username',
          password: '   '
        }
      }).then(function(response) {
        return response.data.value
      })
    )
  }
  return Promise.all(finalArr).catch(function(error) { console.log(error) })
}

您承认,您拥有的代码非常混乱,我同意其他答案,您可以考虑使用await / async语法。