2016-11-28 55 views
5

Tôi đang cố gắng thực hiện một bộ đếm tiến độ đơn giản từ 0% đến 100% trong khi chương trình của tôi tìm nạp dữ liệu thời tiết. Yêu cầu API được thực hiện bởi getLocation() bên trong số index.ios.js gọi fetchWeather() bên trong số weatherApi.js. Có cách nào để đo lường tiến độ của yêu cầu API của tôi được thực hiện bởi hàm tìm nạp không? Nếu không, cách tốt nhất để triển khai thanh tải là gì?Làm cách nào để tạo thanh tiến trình cho yêu cầu API trong React Native?

weatherAPI.js

const rootUrl ='http://api.openweathermap.org/data/2.5/weather?appid=fcea54d0ceade8f08ab838e55bc3f3c0' 

export const fetchWeather = (lat,lon) => { 

    const url = rootUrl+'&lat='+lat+'&lon='+lon+"&units=metric" 
    console.log(url) 

    return fetch(url) 
    .then(res => res.json()) 
    .then(json => ({ 
     temp: json.main.temp, 
     weather: json.weather[0].main 
    })) 

} 

index.ios.js

import React, {Component} from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    StatusBar 
    } from 'react-native' 

import Icon from 'react-native-vector-icons/Ionicons' 
import {fetchWeather} from './weatherAPI' 
import Highlight from 'react-native-highlight-words' 

const iconNames = { 
    Default: 'md-time', 
    Clear: 'md-sunny', 
    Rain: 'md-rainy', 
    Thunderstorm: 'md-thunderstorm', 
    Clouds: 'md-cloudy', 
    Snow: 'md-snow', 
    Drizzle: 'md-umbrella', 
} 

const phrases = { 

    Default:{ 
     title: "Fetchin the Weather", 
     subtitle: "Be patient, you're witnessing a miracle", 
     highlight: ["Fetchin"], 
     color: "#636363", 
     background: "#9C9C9C" 
    }, 

    Clear: { 
     title: "CLEAR.", 
     subtitle: "You Better Go Outside", 
     highlight: ["CLEAR"], 
     color:"#E32500", 
     background: "#FFD017" 
    }, 
    Rain: { 
     title: "It's Raining", 
     subtitle: "You guessed it", 
     highlight: ["Raining"], 
     color:"#004A96", 
     background:"#2F343A" 
    }, 
    Thunderstorm: { 
     title: "Not Just Raining, It's Storming", 
     subtitle: "Free shower", 
     highlight: ["Storming"], 
     color:"#FBFF46", 
     background:"#020202" 
    }, 
    Clouds: { 
     title: "Clouds for Days", 
     subtitle: "Cotton candy skies", 
     highlight: ["Days"], 
     color:"#0044FF", 
     background: "#939393" 

    }, 
    Snow: { 
     title: "Oh Yeah Bud. It's Snowin'", 
     subtitle: "Make a snow angel bud", 
     highlight: ["Snowin'"], 
     color:"#021D4C", 
     background:"#15A678" 

    }, 
    Drizzle: { 
     title: "Just a Wee Ol' Drizzle Lads", 
     subtitle: "Free shower", 
     highlight: ["Wee", "Ol'"], 
     color:"#dbdbdb", 
     background:"#1FBB68" 

    }, 
} 

class App extends Component { 


    componentWillMount() { 

    this.state = { 

     temp: 0, 
     weather: 'Default' 
    } 

    } 

    componentDidMount() { 
    this.getLocation() 
} 

    getLocation() { 
    navigator.geolocation.getCurrentPosition(
     posData => fetchWeather(posData.coords.latitude,posData.coords.longitude) 
     .then(res => this.setState({ 
     temp:Math.round(res.temp), 
     weather: res.weather 
     })), 
     error => alert(error), 
     {timeout: 10000} 
    ) 
    } 


    render(){ 
     console.log(this.state.weather) 
     return(
     <View style={[styles.container, {backgroundColor: phrases[this.state.weather].background}]}> 
      <StatusBar hidden={true}/> 
      <View style={styles.header}> 
      <Icon name={iconNames[this.state.weather]} size={80} color={'white'}/> 
      <Text style={styles.temp}>{this.state.temp}°</Text> 
      </View> 
      <View style={styles.body}> 
      <Highlight 
       style={styles.title} 
       highlightStyle={{color: phrases[this.state.weather].color}} 
       searchWords={phrases[this.state.weather].highlight} 
       textToHighlight={phrases[this.state.weather].title} 
       /> 
      <Text style={styles.subtitle}>{phrases[this.state.weather].subtitle}</Text> 
      </View> 
     </View> 
     ) 
    } 
} 

const styles = StyleSheet.create({ 

    container: { 
     flex:1, 
     backgroundColor:'#FFD017' 
    }, 


    header: { 
     flexDirection:'row', 
     alignItems:'center', 
     justifyContent:'space-around', 
     flex:1, 

    }, 
    temp: { 
     fontFamily: 'HelveticaNeue-Bold', 
     fontSize: 45, 
     color:'white' 

    }, 

    body: { 
     alignItems:'flex-start', 
     justifyContent:'flex-end', 
     flex:5, 
     margin:10 

    }, 

    title: { 
     fontFamily: 'HelveticaNeue-Bold', 
     fontSize: 90, 
     color:'white', 
     marginBottom:5 

    }, 
    subtitle: { 
     fontFamily: 'HelveticaNeue-Medium', 
     fontSize: 16, 
     color:'white' 

    } 



}); 

AppRegistry.registerComponent('IsItRaining',() => App) 
+1

Có sự kiện onProgress trong trình duyệt. Bạn không chắc chắn cách thức hoạt động với node.js trong phản ứng gốc. Có lẽ bạn nên thử một thư viện XHR khác. – abeikverdi

+1

Xem [axios] (https://www.npmjs.com/package/axios) và cả [thư viện] này (https://www.npmjs.com/package/axios-status) – abeikverdi

+1

@LaurentL, tôi thấy bạn luôn nói điều gì đó tốt về thời tiết! ;) –

Trả lời

4

Các fetch API không bao gồm any progress callbacks, vì vậy lựa chọn của bạn là một trong hai sử dụng XMLHttpRequest, được hỗ trợ đầy đủ trong React Native, hoặc một thư viện về cơ bản sẽ xây dựng trên đỉnh đó. Ví dụ, bạn có thể sửa đổi chức năng fetchWeather của bạn để làm:

export const fetchWeather = (lat,lon, progress) => { 
return new Promise((resolve, reject) => { 
    const url = rootUrl+'&lat='+lat+'&lon='+lon+"&units=metric" 
    console.log(url) 
    var oReq = new XMLHttpRequest(); 

    oReq.addEventListener("progress", progress); 
    oReq.open('GET', url); 
    oReq.send(); 
    oReq.onreadystatechange = function() { 
     if (oReq.readyState == XMLHttpRequest.DONE) { 
      let data = JSON.parse(oReq.responseText); 
      resolve({temp: data.main.temp, weather: json.weather[0].main}); 
     } 
    } 
}); 
} 

đâu tiến bộ là một callback mà bạn cập nhật trạng thái. Ví dụ, trong thành phần của bạn, thêm chức năng:

function updateProgress (oEvent) { 
    if (oEvent.lengthComputable) { 
    var progress = oEvent.loaded/oEvent.total; 
    this.setState({progress}) 
    } else { 
    // Unable to compute progress information since the total size is unknown 
    } 
} 

Sau đó, các cuộc gọi trở thành:

fetchWeather(posData.coords.latitude,posData.coords.longitude, this.updateProgress.bind(this)) fetchWeather(posData.coords.latitude,posData.coords.longitude) 

Ví dụ được chuyển thể từ MDN.

+0

Wow! Đây là một câu trả lời tốt hơn tôi có thể mong đợi! Cảm ơn bạn rất nhiều vì đã dành thời gian để xem xét vấn đề của tôi và thực sự viết mã để chứng minh điều đó. – LaurentL

+0

Rất vui! Hãy cho chúng tôi biết nếu bạn gặp phải bất kỳ vấn đề nào khi triển khai nó :) – martinarroyo

Các vấn đề liên quan