从Axios API返回数据

132
我正在尝试使用Node.JS应用程序进行API请求的发送和接收。它使用Axios向另一个服务器发出get请求,并使用从所接收的API调用中获得的数据。第二段代码是在脚本返回所调用的数据时。它实际上会将其写入控制台,但不会在第二个API中发送回来。
function axiosTest() {
    axios.get(url)
        .then(function (response) {
            console.log(response.data);
            // I need this data here ^^
            return response.data;
        })
        .catch(function (error) {
            console.log(error);
        });
}

...

axiosTestResult = axiosTest(); 
response.json({message: "Request received!", data: axiosTestResult});

我知道这样做是不对的,但我只是想找到一种方法使它工作。我唯一能够从中获取数据的方式是通过console.log,在我的情况下并不有用。


2
我觉得人们在这个问题上有点过了。基本上,你的axiosTest函数中缺少一个返回值,并且你没有等待它的结果。在处理Promises时,始终返回Promise并在需要结果时等待它。 - Nielsvandenbroeck
11个回答

217

问题在于原始的 axiosTest() 函数没有返回 Promise。以下是更详细的解释:

问题在于原始的 axiosTest() 函数没有返回 promise。以下是更详细的解释:

function axiosTest() {
    // create a promise for the axios request
    const promise = axios.get(url)

    // using .then, create a new promise which extracts the data
    const dataPromise = promise.then((response) => response.data)

    // return it
    return dataPromise
}

// now we can use that data from the outside!
axiosTest()
    .then(data => {
        response.json({ message: 'Request received!', data })
    })
    .catch(err => console.log(err))

这个函数可以更简洁地编写:

function axiosTest() {
    return axios.get(url).then(response => response.data)
}

或者使用 async/await:

async function axiosTest() {
    const response = await axios.get(url)
    return response.data
}

7
如果函数axiosTest()在调用它的函数所在的不同文件中,我似乎无法使其正常工作:axiosTest().then... 在这种情况下是否需要做任何特殊处理? - mbenhalima
1
对我来说也是一样的,我想把axiosTest()函数放在一个不同的文件中,而不是调用函数所在的文件。有没有人有这方面的想法? - raphael_mav
1
听起来你只是想知道如何将代码拆分成单独的文件。可以考虑使用JavaScript模块。 - kingdaro
3
你是真正的MVP @kingdaro。我已经卡在我的代码上很长时间了,然后我发现了你的答案,简直就是个传奇。 - leveeee
1
在我的情况下,只需在axios.post()之前使用await就能使其正常工作。 - Blues Clues
显示剩余3条评论

22

我知道这篇文章已经有些年头了。但是我看到有几个人试图使用async和await来回答,但是他们做错了。这应该为任何新的参考提供了清晰的解释。

更新:2023年5月 这个答案仍然受到很多关注,并且已经更新/修复为使用箭头函数。

const axiosTest = async () => {
  try {
    // use data destructuring to get data from the promise object
    const { data: response } = await axios.get(url); 
    return response;
  } catch (error) {
    console.log(error);
  }
};

2
这是正确的答案-当你在应用中调试代码时,调用上述函数的函数以及链中的所有其他函数将似乎返回,但稍后代码将从await之后开始执行。您需要使应用中的所有函数都异步化,并使用await调用所有函数。在调用者的返回语句和下一行代码上设置断点-一切都会变得清晰明了。 - Rodney P. Barbati

15

您可以通过一个简单的回调函数来填充所需的数据,假设我们有一个名为lst的列表需要填充, 我们有一个填充该列表的函数。

const lst = [];  
const populateData = (data) => {lst.push(data)} 

现在我们可以将回调函数传递给执行 axios 调用的函数,并在从响应中获取数据时填充列表。

现在,我们创建一个发出请求的函数,并将 populateData 作为回调函数传递。

function axiosTest (populateData) {
        axios.get(url)
       .then(function(response){
               populateData(response.data);
        })
        .catch(function(error){
               console.log(error);
         });
}   

2
谢谢@Fahad_Shovon!这个问题让我花了一天时间来解决,但是幸好通过你的解决方案我终于解决了。 - mbenhalima
你不想看到这种事情发生,朋友们。 - Cameron Wilby

5
axios库创建了一个Promise()对象。Promise是JavaScript ES6中的内置对象。当使用new关键字实例化此对象时,它将函数作为参数。这个单一的函数又接受两个参数,每个参数也是一个函数——resolve和reject。
Promise执行客户端代码,并且由于JavaScript异步流的“酷”特性,可能会最终解决其中一件或两件事情,即该解决(通常被认为是Promise成功的语义等效)或拒绝(广泛认为是错误的解决)。例如,我们可以保留对某个Promise对象的引用,该对象包括将“最终”返回响应对象的函数(将包含在Promise对象中)。因此,我们可以使用这样的Promise的一种方式是等待承诺解决为“某种响应”。
您可能会提出,我们不希望等待API返回调用数秒钟!我们希望我们的UI能够在等待API响应的同时做一些事情。否则,我们的用户界面将非常缓慢。那么我们如何解决这个问题?
好吧,Promise是“异步”的。在执行JavaScript代码的引擎的标准实现中(比如Node或常见的浏览器),它将在另一个进程中解析,而我们无法预先知道Promise的结果。通常的策略是将我们的函数(即类的React setState函数)发送到Promise,根据某种条件(取决于我们选择的库)进行解析。这将导致基于Promise解决方案更新本地JavaScript对象。因此,您可以将函数想象为您可能向异步方法“发送”的获取器和设置器(在传统的OOP中)。
我将在这个例子中使用Fetch,以便您可以尝试理解Promise中发生的事情,并查看是否可以在axios代码中复制我的思路。Fetch基本上类似于axios,但没有内置的JSON转换,并具有不同的解决Promise的流程(您应该参考axios文档来学习)。
GetCache.js
const base_endpoint = BaseEndpoint + "cache/";
// Default function is going to take a selection, date, and a callback to execute.
// We're going to call the base endpoint and selection string passed to the original function.
// This will make our endpoint.
export default (selection, date, callback) => {  
  fetch(base_endpoint + selection + "/" + date) 
     // If the response is not within a 500 (according to Fetch docs) our promise object
     // will _eventually_ resolve to a response. 
    .then(res => {
      // Lets check the status of the response to make sure it's good.
      if (res.status >= 400 && res.status < 600) {
        throw new Error("Bad response");
      }
      // Let's also check the headers to make sure that the server "reckons" its serving 
      //up json
      if (!res.headers.get("content-type").includes("application/json")) {
        throw new TypeError("Response not JSON");
      }
      return res.json();
    })
    // Fulfilling these conditions lets return the data. But how do we get it out of the promise? 
    .then(data => {
      // Using the function we passed to our original function silly! Since we've error 
      // handled above, we're ready to pass the response data as a callback.
      callback(data);
    })
    // Fetch's promise will throw an error by default if the webserver returns a 500 
    // response (as notified by the response code in the HTTP header). 
    .catch(err => console.error(err));
};

现在我们已经编写好了 GetCache 方法,让我们看一下如何更新 React 组件的状态,以示例为例...

某些 React 组件.jsx

// Make sure you import GetCache from GetCache.js!

resolveData() {
    const { mySelection, date } = this.state; // We could also use props or pass to the function to acquire our selection and date.
    const setData = data => {
      this.setState({
        data: data,
        loading: false 
        // We could set loading to true and display a wee spinner 
        // while waiting for our response data, 
        // or rely on the local state of data being null.
      });
    };
  GetCache("mySelelection", date, setData);
  }

最终,你并不是像返回数据那样去做,我是说你可以这么做,但更符合惯用法的方式是改变你的思考方式... 现在我们正在向异步方法发送数据。

愉快地编码吧!


4

axiosTest() 需要返回 axios.get,后者又会返回一个 Promise

然后,可以使用 then 来执行一个函数,当该 Promise 被解决时。

更多信息请参见Promise

或者,可以在某个async函数的作用域内使用 await

// Dummy Url.
const url = 'https://jsonplaceholder.typicode.com/posts/1'

// Axios Test.
const axiosTest = axios.get

// Axios Test Data.
axiosTest(url).then(function(axiosTestResult) {
  console.log('response.JSON:', {
    message: 'Request received',
    data: axiosTestResult.data
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>


2
我认为在客户端js代码中非常重要的一个原则是将数据处理和UI构建逻辑分别放入不同的函数中,这个原则也适用于axios数据获取。通过这种方式,您的控制流程和错误处理将变得更加简单和易于管理,正如从此处ok fetchNOK fetch所示。最初的回答。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>

       function getUrlParams (){
          var url_params = new URLSearchParams();
          if( window.location.toString().indexOf("?") != -1) {
             var href_part = window.location.search.split('?')[1]
             href_part.replace(/([^=&]+)=([^&]*)/g,
                function(m, key, value) {
                   var attr = decodeURIComponent(key)
                   var val = decodeURIComponent(value)
                   url_params.append(attr,val);
             });
          }
          // for(var pair of url_params.entries()) { consolas.log(pair[0]+ '->'+ pair[1]); }
          return url_params ;
       }


      function getServerData (url, urlParams ){
          if ( typeof url_params == "undefined" ) { urlParams = getUrlParams()  }
          return axios.get(url , { params: urlParams } )
          .then(response => {
             return response ;
          })
          .catch(function(error) {
             console.error ( error )
             return error.response;
          })
       }

    // Action !!!
    getServerData(url , url_params)
        .then( response => {
           if ( response.status === 204 ) {
              var warningMsg = response.statusText
              console.warn ( warningMsg )
              return
           } else if ( response.status === 404 || response.status === 400) {
              var errorMsg = response.statusText // + ": "  + response.data.msg // this is my api
              console.error( errorMsg )
              return ;
           } else {
              var data = response.data
              var dataType = (typeof data)
              if ( dataType === 'undefined' ) {
                 var msg = 'unexpected error occurred while fetching data !!!'
                 // pass here to the ui change method the msg aka
                 // showMyMsg ( msg , "error")
              } else {
                 var items = data.dat // obs this is my api aka "dat" attribute - that is whatever happens to be your json key to get the data from
                 // call here the ui building method
                 // BuildList ( items )
              }
              return
           }

        })




    </script>

0
经过6个小时的反复尝试,我发现这其实只是一个一行代码的问题。如果你在干预axios生命周期,并且遇到了问题,可能是你忘记加上这一行代码了:
componentDidMount() {
    this.requestInterceptor = axios.interceptors.request.use((request) => {
    this.updateApiCallFor(request.url, true);
    return request;
  });

    this.responseInterceptor = axios.interceptors.response.use((response) => {
    this.updateApiCallFor(response.config.url, false);

    return response; // THIS LINE IS IMPORTANT !

  }, (error) => {
    this.updateApiCallFor(error.config.url, false);
    throw error;
  });

0

async 使函数 返回一个 Promise

await 使函数 等待一个 Promise


异步/等待代码

// https://www.npmjs.com/package/axios
const axios = require('axios')

/* --- */

async function axiosTest() {

    let promiseAxios = axios.get( 'https://example.com' )

    /* --- */

    console.log( await promiseAxios )
        
}

/* --- */

axiosTest()

replit.com Stackoverflow - 从 Axios API 返回数据

replit.com Stackoverflow - 如何从异步函数中返回值


异步/等待代码 带返回值

// https://www.npmjs.com/package/axios
const axios = require('axios')

/* --- */

async function axiosTest() {

    console.log( await promiseAxios() )
        
}

/* --- */

axiosTest()

/* --- */

// create function for promise axios and return it
function promiseAxios() {

    return axios.get( 'https://example.com' )
    
}

replit.com Stackoverflow - 从 Axios API 返回数据 - return

replit.com Stackoverflow - 如何从异步函数中返回值 - return


-1

试一下这个,

function axiosTest() {
    axios.get(url)
        .then(response => response.data)
        .catch(error => error);
}

async function getResponse () {
        const response = await axiosTest();
        console.log(response);
}

getResponse()

它可以工作,但是每个想要获取响应的函数都需要成为异步函数或使用额外的.then()回调。

function axiosTest() {
    axios.get(url)
        .then(response => response.data)
        .catch(error => error);
}

async function getResponse () {
        axiosTest().then(response => {
                console.log(response)
        });
}

getResponse()

如果有人知道避免这种情况的方法,请告诉我。

同时,可以查看Katsiaryna(Kate)LupachovaDev.to上的文章,我认为它会有所帮助。


-2
    async handleResponse(){
      const result = await this.axiosTest();
    }

    async axiosTest () {
    return await axios.get(url)
    .then(function (response) {
            console.log(response.data);
            return response.data;})
.catch(function (error) {
    console.log(error);
});
}

您可以在https://flaviocopes.com/axios/#post-requests中查找检查url,并在此帖子的GET部分中找到一些相关信息。


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