我有這個流星應用程序發送數據到api,然後使用在網站發回的數據。但是,當我調用獲取api數據的函數,uploadToCloudinary()
有一個回調,我發現它運行兩次。其中一個文檔正確插入正確的信息,另一個缺少res.data.secure_url
。我是不是正在做回調事情,還是因爲它是非阻塞代碼,所以我認爲(糾正我,如果我錯了),當imageURL.push
函數執行時,它不能找到一個res
,所以它和其他代碼第一次,然後當它發現res
它推它並創建另一個文檔。流星 - 回調執行兩次
import { Meteor } from "meteor/meteor"
import React from "react";
import { withRouter, Link } from "react-router-dom";
import SimpleSchema from "simpl-schema";
import axios from "axios"
import { SubjectRoutes } from "./subjectRoutes/subjectRoutes";
import "../methods/methods";
import Menu from "./subComponents/Menu";
class AddNote extends React.Component{
constructor(props){
super(props);
this.state = {
message: "",
loginMessage: (<div></div>),
urls: []
};
}
renderSubjects(subjects){
return subjects.map((item) => {
return <option key={item}>{item}</option>
})
}
componentWillMount() {
Meteor.subscribe('user');
}
addNote(e){
e.preventDefault();
let title = this.refs.title.value;
let subject = this.refs.subject.value;
let description = this.refs.description.value;
let allUrls = [this.refs.imageURL.value].concat(this.state.urls);
let imageURL = allUrls.filter(function(entry) { return entry.trim() != ''; });
let userId = Meteor.userId();
let userEmail = Meteor.user().emails[0].address;
let createdAt = Date.parse(new Date());
let unit = this.refs.unit.value;
let file = this.refs.fileInput.files[0];
if(!Meteor.userId()){
this.setState({
message: "You need to login before you can add a note",
loginMessage: <Link to="/login">Login</Link>
})
throw new Meteor.Error(400, "User is not signed in.")
}
if(title && subject && description && unit){
if(imageURL.length == 0 && file == undefined){
this.setState({ message: "You need to enter an image." })
return;
}
console.log(imageURL.length, file)
if(imageURL){
let noteInfo = { title, subject, description, imageURL, userId, userEmail, createdAt, unit };
Meteor.call("notes.insert", noteInfo, (err, res) => {
if(err){
this.setState({ message: "Please enter a valid image URL." });
}else{
this.props.history.push("/")
}
})
}
if(file){
let noteInfo = { title, subject, description, imageURL, userId, userEmail, createdAt, unit };
this.uploadToCloudinary(file, (err, res) => {
imageURL.push(res.data.secure_url);
Meteor.call("notes.insert", noteInfo, (err, res) => {
//problem .......inserting 2 docs, one empty and one with proper data
console.log("CALLED")
if(err){
this.setState({message: err.reason});
console.log(err);
}else{
this.props.history.push("/")
}
})
});
}
}
}
addLink(){
let file = this.refs.fileInput.files[0];
if(this.refs.imageURL.value || file != undefined){
if(this.state.urls.length < 10){
if(!this.state.urls.includes(this.refs.imageURL.value)){
const URLSchema = new SimpleSchema({
imageURL:{
type:String,
label:"Your image URL",
regEx: SimpleSchema.RegEx.Url
}
}).validate({ imageURL:this.refs.imageURL.value })
let urls = this.state.urls.concat([this.refs.imageURL.value]);
this.setState({ urls });
this.refs.imageURL.value == "";
}else{
this.setState({ message: "You already inserted this note." })
}
}else{
this.setState({ message: "Only allowed 10 notes per upload. "})
}
}else{
this.setState({ message: "Please enter a note." })
}
}
uploadToCloudinary(file, callback){
const CLOUDINARY_URL = "MY_CLOUDINARY_URL";
const CLOUDIARY_UPLOAD_PRESET = "MY_CLOUDIARY_UPLOAD_PRESET"
let formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", CLOUDIARY_UPLOAD_PRESET)
axios({
url: CLOUDINARY_URL,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: formData
}).then(function(res){
callback(new Meteor.Error(400, "Error, cannot connect to cloudinary."), res);
}).catch(function(err){
console.log(err);
})
console.log(file);
}
render(){
return(
<div>
<form onSubmit={this.addNote.bind(this)}>
<Menu />
<p>*Just a friendly reminder: If you cannot read the note yourself,
others cannot as well. Please make sure your notes are clear and
easy to read.*</p>
<h1>Add a note</h1>
<br />
<input className="addNote-input" id="title" ref="title" type="text" placeholder="Title" autoComplete="off" />
<br />
<select ref="subject">
<option selected disabled value="">Choose a subject</option>
{this.renderSubjects(SubjectRoutes)}
</select>
<br />
<input className="addNote-input" id="description" ref="description" placeholder="Description Here..." autoComplete="off" />
<br />
<Link to="/questions">What is this?</Link><br />
<div className="inline full">
<div className="left">
<input id="imageUrl" className="addNote-input insert-link" ref="imageURL" placeholder="Enter image URL here" autoComplete="off" />
</div>
or
<div className="right">
<input className="addNote-input inline" type="file" ref="fileInput" onChange={this.readImage} id="fileInput" autoComplete="off"/>
</div>
<div className="full inline-block">
<span onClick={this.addLink.bind(this)} id="addLink">+</span>
<span>({this.state.urls.length})</span>
</div>
</div>
<input className="addNote-input" placeholder="Subject Unit" type="text" ref="unit" autocomplete="off" />
<br />
<button>Add Note</button>
<br />
<div className="alert alert-danger">Error: {this.state.message}</div>
<br />
{this.state.loginMessage}
</form>
</div>
)
}
}
export default withRouter(AddNote);
PS的函數uploadToCloudinary()只接收數據作爲參數,並把它發送到一個API然後將其放入一個回調返回的對象。而且console.log("CALLED")
只執行一次,這對我來說真是令人困惑,因爲它創建了兩個文檔,所以它應該運行兩次。提前致謝!
請添加你的'uploadToCloudinary'函數的源代碼。 – Styx
這是什麼代碼?有沒有火焰模板?何反應?那裏有什麼反應嗎?有一種常見的情況,即在反應性代碼塊中執行方法調用,並且結束運行的次數超過預期。 –
@MichelFloyd它是一個反應組件的一部分我認爲爲簡單起見,放置運行兩次而不是整個組件的函數會更容易,但如果這是您需要的,我會發布上面的整個組件。 –