मैं एकाधिक यूआरएल एपीआई लाना चाहता हूं, लेकिन जब मैं कोशिश कर रहा हूं तो इसे एक त्रुटि फेंक दी गई है 'त्रुटि: अमान्य तर्क कॉलबैक के रूप में पारित किया गया। एक समारोह की उम्मीद है। इसके बजाय प्राप्त: [वस्तु वादा]'। परीक्षण के कारण कंसोल में डेटा प्रदर्शित होता है, और मैं इस तरह चाहता था: 4 अलग-अलग URL से 4 ऑब्जेक्ट। लेकिन बाद में मैं उन वस्तुओं को एक खाली सरणी "ऑलसिटीज" में जोड़ना चाहता था जो पहले से ही राज्य में घोषित है। नीचे दिए गए इस कोड को कैसे ठीक करें? बीटीडब्ल्यू त्रुटि तब होती है जब मैं लाइन पर यूआरएल लाने के बाद राज्य बदलना चाहता हूं:

this.setState({
              allcities: [].concat(...data)
            });

नीचे कोड:

getWeatherAll = () => {
    const urls = [
      `http://api.openweathermap.org/data/2.5/forecast?id=658225&appid=${API_KEY}&units=metric`,
      `http://api.openweathermap.org/data/2.5/forecast?id=655195&appid=${API_KEY}&units=metric`,
      `http://api.openweathermap.org/data/2.5/forecast?id=650225&appid=${API_KEY}&units=metric`,
      `http://api.openweathermap.org/data/2.5/forecast?id=634964&appid=${API_KEY}&units=metric`
    ];
    this.setState({
      temp: '',
      city: '',
      icon: '',
      description: '',
      time: '',
      wind: '',
      humidity: '',
      hours: [],
      cityId: ''

    }, Promise.all(
      urls.map(url =>
        fetch(url)
          .then(res => res.json())
          .then(data => {
            console.log(data);
            this.setState({
              allcities: [].concat(...data)
            });
          })
      ))
    )
  };
0
Magda Aderibigbe 25 मार्च 2020, 14:42

5 जवाब

खराब setState कॉलबैक तर्क। Promise.all कॉल एक वादा देता है, न कि एक फ़ंक्शन [आवश्यकतानुसार]।

यह एक समारोह बनाने के लिए पर्याप्त है, ऐसा कुछ:

this.setState({
  temp: '',
  // ...
}, () => Promise.all(
  urls.map(url =>
    fetch(url)
      .then(res => res.json())
      .then(data => {
        console.log(data);
        this.setState({
          allcities: [].concat(...data)
        });
      })
  ...
  ).then( () => console.log("done") )
) 

ऊपर के साथ समस्या

प्रत्येक setState पहले की स्थिति को अधिलेखित कर देता है। इसे setState में फ़ंक्शन का उपयोग करके ठीक किया जा सकता है:

this.setState( (prevState, props) => ({
  allcities: [...prevState.allcities, data]
}));

क्या यह इष्टतम है?

निश्चित रूप से नहीं। डेटा अलग-अलग क्रम में आ सकता है (कभी-कभी यह मायने रखता है) और हम setState को कई बार कॉल कर रहे हैं, जबकि Promise.all हमारे लिए मूल रूप से डेटा एकत्र कर सकते हैं (मूल ऑर्डर को संरक्षित करते हुए) और हम केवल एक बार setState कर सकते हैं :

this.setState({
  temp: '',
  // ...
}, () => Promise.all(
  urls.map(url =>
    fetch(url)
      .then(res => res.json())
      .then(data => {
        // console.log(data);
        return data;
      })
    )
  ).then( responses => {
    this.setState({
      allcities: responses
    });
    console.log("done")
  })
) 

सरणियों में परिभाषित अनुरोधों के साथ (.map एक सरणी देता है) आप डिबगिंग के दौरान पठनीयता में सुधार कर सकते हैं:

const requestsLogged = urls.map(url =>
  fetch(url)
    .then(res => res.json())
    .then(res => {
      console.log("fetch", res)
      return res // this is important
    })
);
Promise.all(requestsLogged).then(data => {
  console.log("all logged", data);
  //this.setState({
  //  allcities: data
  //});
});

बाद में आप इसे छोटा कर सकते हैं:

const requests = urls.map(url => fetch(url).then(res => res.json()));

कार्य उदाहरण

1
xadm 28 मार्च 2020, 15:58

समस्या यह प्रतीत होती है कि आपके पास एक ही fetch पर दो then हैं, कुछ ऐसा प्रयास करें:

Promise.all(
  urls.map(url =>
    fetch(url)
      .then(res => res.json())
  )
).then(data => {
  console.log(data);
  this.setState({
    allcities: [].concat(...data)
  });
})


आपको प्रत्येक अनुरोध से एक जेसन वापस करने की आवश्यकता है, और जब वे सभी हो जाते हैं, तो आप Promise.all के लिए अपने then का उपयोग कर सकते हैं।

यदि यह काम नहीं करता है, तो कृपया एक jsfiddle या कोडपेन बनाने का प्रयास करें जहां हम समस्या देख सकें।

0
avcajaraville 25 मार्च 2020, 14:50

प्रयत्न

this.setState((state, props) => ({
  allcities: [...state.allcities,data]
}));

और क्या आप वह पोस्ट कर सकते हैं जो data दिखता है?

0
Ahmed Jaouadi 25 मार्च 2020, 14:55

आपकी समस्या this.setState को कॉल करने के तरीके से जुड़ी है।

जैसा कि दस्तावेज़ीकरण में वर्णित है, आप दूसरे पैरामीटर के रूप में कॉलबैक फ़ंक्शन का उपयोग कर सकते हैं।

setState(updater, [callback])

आपके मामले में, आप Promise.all को कॉलबैक के रूप में उपयोग कर रहे हैं जो एक फ़ंक्शन नहीं बल्कि एक वादा है।

बदलने के

this.setState({...}, Promise.all(...));

द्वारा

this.setState({..});
Promise.all(...);

या यदि आपको वास्तव में कॉलबैक की आवश्यकता है

this.setState({..}, () => Promise.all(...));
0
Weedoze 25 मार्च 2020, 14:56

ठीक है, मैंने एक नई सरणी जोड़कर इस समस्या को हल किया और सरणी में 4 ऑब्जेक्ट्स (जेसन डेटा) को धक्का दिया और इसके बाद मैंने राज्य बदल दिया। यह काम कर रहा है।

const requests = urls.map(url => fetch(url).then(res => res.json()));
const newArr = [];
Promise.all(requests)
      .then(data => {
        console.log(data);
        newArr.push(data);
        this.setState({
          allCities: [].concat(...newArr)
        });
      })
0
Magda Aderibigbe 27 मार्च 2020, 21:14
इस मामले में यह कोड (पास data के साथ) एक बार चलाया जाना चाहिए ... और आपको अतिरिक्त सरणी की आवश्यकता नहीं है - मेरा अद्यतन उत्तर देखें।
 – 
xadm
25 मार्च 2020, 23:39
कंसोल.लॉग (डेटा) 4 वस्तुओं को प्रदर्शित करता है (4 यूआरएल से प्राप्त)। जब मैं आपके समाधान की कोशिश कर रहा था, तो उसने मुझे एक त्रुटि दी: "urls.map(...).then(...) कोई फ़ंक्शन नहीं है।" इसलिए, पहले मैंने इन वस्तुओं को सरणी में जोड़ा, अब यह काम कर रहा है।
 – 
Magda Aderibigbe
27 मार्च 2020, 21:18
बस इतना ही - एक बार में 4 ऑब्जेक्ट ... त्रुटि सिंटैक्स से हो सकती है, कोष्ठक मिलान ... अपडेट और लिंक देखें
 – 
xadm
28 मार्च 2020, 15:59