【问题标题】:Chaining async functions doesn't work correctly链接异步函数无法正常工作
【发布时间】:2020-11-08 18:04:14
【问题描述】:

我正在尝试链接两个异步函数,但似乎第二个函数在第一个函数之前执行。 这是我的代码

function performAction(e) {
const ZIP = document.getElementById('zip').value;
const fellings = document.getElementById('feelings').value;
console.log(`${baseURL}${ZIP},us&appid=${key}`);
getWeather(baseURL, ZIP, key,).then((data) => {
    postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: fellings })
}).then(
    updateUI()
)}

这是 getWeather()

const getWeather = async(baseURL, ZIP, key) => {
let URL = `${baseURL}${ZIP}&appid=${key}`;
const res = await fetch(URL)
try{
    const data = await res.json();
    return data;
}catch(error){
    console.log("error", error);
}}

这是 postData(),它应该在 getWeather 函数执行后执行,但事实并非如此。

const postData = async ( url = '', data = {}) => {
console.log(`This is what we fetch ${data.temperature}`);
console.log(`This is what we fetch ${data.date}`);
console.log(`This is what we fetch ${data.userResponse}`);
  const response = await fetch(url, {
  method: 'POST', 
  credentials: 'same-origin',
  headers: {
      'Content-Type': 'application/json',
  },
 // Body data type must match "Content-Type" header        
  body: JSON.stringify(data), 
});
try {
    const newData = await response.json();
    console.log(`This is the new Data ${newData.temperature}`);
    return newData;
}catch(error){
  console.log("error", error);
}}

这是 updateUI()

const updateUI = async () => {
const request = await fetch('/getweather');
try{
  const allData = await request.json();
  console.log('Get request');
        document.getElementById('date').innerHTML = allData.date;
        document.getElementById('temp').innerHTML = allData.temperature;
        document.getElementById('content').innerHTML = allData.userResponse;
}catch(error){
  console.log("error", error);
}}

发生的情况是 UI 首先更新,因此它第一次获得 undefined 的值,当我重新加载页面并输入新数据时,UI 将使用上次的数据进行更新。

【问题讨论】:

    标签: javascript node.js express asynchronous async-await


    【解决方案1】:

    你的postData() 也是一个异步函数。因此,您也必须等待:

    getWeather(baseURL, ZIP, key,).then(async (data) => {
        await postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: fellings })
    }).then(
        updateUI()
    )}
    

    我有一段时间没做过javascript了,但我想这样更清楚:

    const performAction = async (e) => {
    const ZIP = document.getElementById('zip').value;
    const fellings = document.getElementById('feelings').value;
    console.log(`${baseURL}${ZIP},us&appid=${key}`);
    try{
    const data = await getWeather(baseURL, ZIP, key,);
    const postData= await postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: fellings });
    } catch(e) {
    console.log(e)
    } finally {
        updateUI();
    }
    

    您也不必等待解析 json 并且 try catch 应该包含您的请求:

    const postData = async ( url = '', data = {}) => {
    console.log(`This is what we fetch ${data.temperature}`);
    console.log(`This is what we fetch ${data.date}`);
    console.log(`This is what we fetch ${data.userResponse}`);
    try {
      const response = await fetch(url, {
      method: 'POST', 
      credentials: 'same-origin',
      headers: {
          'Content-Type': 'application/json',
      },
     // Body data type must match "Content-Type" header        
      body: JSON.stringify(data), 
    });
    
        const newData = response.json();
        console.log(`This is the new Data ${newData.temperature}`);
        return newData;
    }catch(error){
      console.log("error", error);
    }}
    

    【讨论】:

    • 使用你的第二个例子,它现在抛出这个错误ReferenceError: Cannot access 'postData' before initialization at HTMLButtonElement.performAction
    • 并且使用您的第一个示例并没有任何区别,它还会在发布数据之前更新 UI。这真的很奇怪,我不知道发生了什么
    • 不幸的是,它仍然不起作用并且行为相同
    • @MarwanElgendy 是的,因为您返回数据而不将其保存在某处:` const data = await postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: 砍伐} );控制台.log(数据); `
    • 我实际上将数据保存在我的服务器端代码中的一个对象中,然后在updateUI 中,我发起一个获取请求以从对象中获取该数据,但它总是在 @ 中发出获取请求987654327@postData中的POST请求前
    【解决方案2】:

    你需要返回从postData返回的promise:

    getWeather(baseURL, ZIP, key,).then((data) => {
       return postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: fellings })
    }).then(() => {
       return updateUI()
    })
    

    另一种写法是这样的:

    async function run() {
       await getWeather(baseURL, ZIP, key)
       await postData('/addweather', {temperature: data.main.temp ,date:newDate, userResponse: fellings })
       await updateUI()
    }
    

    【讨论】:

    • 当我这样做时它会抛出一个错误Uncaught SyntaxError: Unexpected token 'return' 返回只适用于postData() 没有问题,但它不适用于updateUI()
    • 您的 async run() 函数没有意义,因为未定义数据。只是说。
    • data 可以在闭包中定义,但我的目的是展示如何使用 async/await 代替
    猜你喜欢
    • 2019-10-13
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    相关资源
    最近更新 更多