首页 > 解决方案 > Javascript fetch Api 不起作用初学者问题

问题描述

我有一个简单的代码,我正在尝试发送一个帖子,但我的代码有问题。Post 不起作用,在窗帘后面,我有一个简单的后端,它可以 100% 运行。所以问题出在上面的代码上。请帮助我,也许范围有问题?

Api = function() {
  this.header = new Headers({
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  })
};

Api.prototype.buildUrl = function(id) {
  return "http://localhost:3000/db/shop_name/" + id;
};

Api.prototype.post = function(id, data) {

  const urlPost = api.buildUrl(id.value);
  return fetch(urlPost, {
      method: "post",
      body: JSON.stringify(data),
      headers: this.header

   .then(res => res.json()).then(json => console.log(JSON.stringify(json)))
};

Api.prototype.get = function(id) {
  //const urlGet = api.buildUrl(id);
  return fetch(id, {
      method: "GET",
    })
    .then(resp => {
      alert(resp.json());

      return resp.json();
    })
};
Api.prototype.getAlll = function() {
  return fetch(url, {
      method: "GET"
    })
    .then(resp => {
      alert(resp.json());
      return resp.json()
    })
};

Api.prototype.update = function(id, data) {
  const url = api.buildUrl(id);
  return fetch(url, {
      method: "PUT",
      body: JSON.stringify(data)
    })
    .then(resp => {
      return resp.json()
        .catch(error => {
          let notFound = "The server can not find requested resource";
          document.getElementById("stars").innerHTML = notFound + error.status;
        })
    })
};


Api.prototype.addProduct = function(id, data) {
  return this.post(id, data);
};

Api.prototype.deleteProduct = function(id) {
  return this.delete(id);
};

Api.prototype.updateProduct = function(id, data) {
  return this.update(id, data);
};

Api.prototype.getProduct = function(id) {
  return this.get(id);
};
Api.prototype.getAllProducts = function() {
  return this.getAlll;
};

const Main = function() {
  this.id = document.getElementById("id");
  this.addCount = document.getElementById("count");
  this.addName = document.getElementById("name");
  this.addPrice = document.getElementById("price");
};


Main.prototype.add = function() {
  // const ido = this.id.value;
  const data = {
    "price": this.addPrice.value,
    "name": this.addName.value,
    "count": this.addCount.value,
  };
  //  let id = api.buildUrl(this.id.value);
  api.addProduct(this.id, data);
};


Main.prototype.update = function() {
  const data = {
    "price": this.price,
    "name": this.name,
    "count": this.count,
  };
  api.updateProduct(id, data);
};

Main.prototype.delete = function() {
  let id = api.buildUrl(this.id);
  api.deleteProduct(id);

};


Main.prototype.get = function() {
  let id = api.buildUrl(this.id.value);
  api.getProduct(id);

};

Main.prototype.getAll = function() {
  api.getAllProducts();

};

const api = new Api();
const main = new Main();


let addButton = document.getElementById('postBtn');
addButton.addEventListener('click', function() {
  main.add();
});

/*
addButton.addEventListener("click",main.add.bind(main));
*/


let updateButton = document.getElementById("updateBtn");
updateButton.addEventListener("click", function() {
  main.update();
});


let deleteButton = document.getElementById("deleteBtn");
deleteButton.addEventListener("click", function() {
  main.delete();
});

let getButton = document.getElementById("getBtn");
getButton.addEventListener("click", function() {
  main.get();
});


let getAllButton = document.getElementById("getAllBtn");
getAllButton.addEventListener("click", function() {
  let tst = main.getAll();
  console.log(tst);

});

标签: javascriptapifetch

解决方案


我创建了一个仅处理您的post方法的最小工作示例,我认为问题在于您为发布请求“构建” URL 的方式:

Api.prototype.post = function(id, data) {
  // WRONG!
  // const urlPost = api.buildUrl(id)

  // CORRECT!
  const urlPost = this.buildUrl(id)

  return fetch(...)
}

看看这个与你的代码结构相似的例子:

const Api = function() {
  this.headers = new Headers({
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  })
}
Api.prototype.buildUrl = function(id) {
  return `https://jsonplaceholder.typicode.com/posts`
};
Api.prototype.post = function(id, data) {
  const urlPost = this.buildUrl()

  return fetch(urlPost, {
    method: 'POST',
    body: JSON.stringify({
      title: 'foo',
      body: 'bar',
      userId: 1
    }),
    headers: this.headers,
  })
  .then(response => response.json())
};


function main() {
  const API = new Api()
  const submitBtn = document.getElementById(`submitBtn`)
  
  submitBtn.addEventListener(`click`, function() {
    API.post()
      .then(result => {
        console.log(`data was submitted`, Date.now())
        console.log(`result`, result)
      })
      .catch(error => {
        console.error(`handle your errors!`)
      })
  })
}

main()
<button id="submitBtn" type="button">Click to submit data</button>

希望这可以帮助。


编辑

您必须在其他任何地方解决此问题,而不仅仅是post方法。

首先,您无法访问方法api内部,Api.prototype.post因为您正在使用它const,所以它超出了范围,因此this当您尝试在对象实例上调用方法时使用:

const Api = function() { ... }
Api.prototype.buildUrl = function() { ... }
Api.prototype.post = function(id, data) {
  const urlPost = this.buildUrl()
  // ...  
}

const api = new Api()
api.post(...)

其次,始终处理您的错误并确保您catch承诺失败。您很可能无法调试此问题,因为您错过了可以为您提供有关正在发生的事情的线索的错误。

Api.prototype.post = function(id, data) {
  const urlPost = this.buildUrl()

  return fetch(urlPost, {...})
    .then(...)
    .catch(error => { console.log(`error`, error.message) }
}

第三,再次,您遇到了范围问题 -在您的方法和实例api中不可用:ApiMain

Api.prototype.post = function(...) {
  api.buildUrl(...) // NOT IN SCOPE!
}
Main.prototype.getAll = function() {
  api.getAllProducts() // ALSO NOT IN SCOPE
}

改为这样做:

const Main = function(api) {
  this.api = api
  // ...
}
Main.prototype.add = function() {
  const data = {...}
  return this.api.addProduct(this.id, data)
}

const api = new Api()
const main = new Main(api) // PASS `api` TO A CONSTRUCTOR
const btn = document.getElementById(`button`)

btn.addEventListener(`click`, function() {
  main.add()
    .then(...)
    .catch(...)
})

Api返回并在and中修复您的所有方法Main

这是一个工作示例:

const Api = function() {
  this.headers = new Headers({
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  })
}
Api.prototype.buildUrl = function(id) {
  return `https://jsonplaceholder.typicode.com/posts`
};
Api.prototype.post = function(id, data) {
  const urlPost = this.buildUrl()

  return fetch(urlPost, {
    method: 'POST',
    body: JSON.stringify({
      title: 'foo',
      body: 'bar',
      userId: 1
    }),
    headers: this.headers,
  })
  .then(response => response.json())
};
Api.prototype.addProduct = function(id, data) {
  return this.post(id, data)
}

function Main(api) {
  this.api = api
  this.id = 1
}
Main.prototype.add = function() {
  const data = {
    "price": 1,
    "name": "Bob",
    "count": 20
  }
  return this.api.addProduct(this.id, data)
}

const api = new Api()
const main = new Main(api)
const submitBtn = document.getElementById(`submitBtn`)

submitBtn.addEventListener(`click`, function() {
  main.add()
    .then(result => {
      console.log(`data was submitted`, Date.now())
      console.log(`result`, result)
    })
    .catch(error => {
      console.log(`handle your errors!`)
    })
})
<button id="submitBtn" type="button">Click me!</button>


推荐阅读