在异步映射功能中下载图像反应本地

时间:2019-01-16 03:37:11

标签: reactjs react-native asynchronous

我正在尝试对图像元数据对象列表执行异步映射。

对于列表中的每个对象,我检查字符串import React, { Component } from 'react'; import IncomeList from './components/IncomeList'; import ExpenseList from './components/ExpenseList'; import AddItem from './components/AddItem'; import Chart from './components/Chart'; import './App.css'; class App extends Component { constructor(){ super() this.state = { incomeItems: [], expenseItems: [], totalIncome: 0, totalExpense: 0, color: 'black', incEarned: 0, incInvest: 0, incSales: 0, incRe: 0, incServices: 0, incOther: 0, incEarnedPCT: 0, incInvestPCT: 0, incSalesPCT: 0, incRePCT: 0, incServicesPCT: 0, incOtherPCT: 0, chartData: {} } this.addBudgetItem = this.addBudgetItem.bind(this); this.addExpenseItem = this.addExpenseItem.bind(this); this.deleteIncomeItem = this.deleteIncomeItem.bind(this); this.deleteExpenseItem = this.deleteExpenseItem.bind(this); } addBudgetItem (item, amount, category) { let newIncomeTotal = this.state.totalIncome + parseInt(amount); this.setState( { incomeItems: [...this.state.incomeItems, {item: item, amount: amount, category: category}], totalIncome: newIncomeTotal }, () => { const newIncList = this.state.incomeItems; let incEarned = this.state.incEarned; let incInvest = this.state.incInvest; let incSales = this.state.incSales; let incRe = this.state.incRe; let incServices = this.state.incServices; let incOther = this.state.incOther; let incEarnedPCT = 0; let incInvestPCT = 0; let incSalesPCT = 0; let incRePCT = 0; let incServicesPCT = 0; let incOtherPCT = 0; newIncList.map((item) => { if(item.category === 'earned'){ incEarned += parseInt(item.amount); incEarnedPCT = incEarned/parseInt(this.state.totalIncome); } else if (item.category === 'invest'){ incInvest += parseInt(item.amount); incInvestPCT = incInvest/parseInt(this.state.totalIncome); } else if (item.category === 'sales'){ incSales += parseInt(item.amount); incSalesPCT = incSales/parseInt(this.state.totalIncome); } else if (item.category === 're'){ incRe += parseInt(item.amount); incRePCT = incRe/parseInt(this.state.totalIncome); } else if (item.category === 'services'){ incServices += parseInt(item.amount); incServicesPCT = incServices/parseInt(this.state.totalIncome); } else { incOther += parseInt(item.amount); incOtherPCT = incOther/parseInt(this.state.totalIncome); } }) //let newData = [incEarnedPCT, incInvestPCT, incSalesPCT, incRePCT, incServicesPCT, incOtherPCT]; this.setState({ incEarnedPCT: incEarnedPCT, incInvestPCT: incInvestPCT, incSalesPCT: incSalesPCT, incRePCT: incRePCT, incServicesPCT: incServicesPCT, incOtherPCT: incOtherPCT, chartData: { labels: ['Earned', 'Investments', 'Sales', 'Real Estate', 'Services', 'Other'], datasets: [ { label: 'Income Distribution', backgroundColor: ['rgba(250,75,185,0.2)', 'rgba(255,99,132,0.2)', 'rgba(255,90,132,0.5)', 'rgba(255,80,110,0.2)', 'rgba(235,75,150,.2)'], data: [50, 55, 3, 44, 25, 60] } ] } }, () => { console.log(`Earned: ${incEarned} PCT: ${this.state.incEarnedPCT}\n Invest: ${incInvest} PCT: ${this.state.incInvestPCT}\n Sales: ${incSales} PCT: ${this.state.incSalesPCT}\n Real Estate: ${incRe} PCT: ${this.state.incRePCT}\n Services: ${incServices} PCT: ${this.state.incServicesPCT}\n Other: ${incOther} PCT: ${this.state.incOtherPCT}`); alert(`CURRENT DATA: ${this.state.chartData.datasets[0].data}`); }) }) } addExpenseItem (expItem, expAmount, expCategory) { let newExpenseTotal = this.state.totalExpense + parseInt(expAmount); this.setState({ expenseItems: [...this.state.expenseItems, {expItem: expItem, expAmount: expAmount, expCategory: expCategory}], totalExpense: newExpenseTotal }) } deleteIncomeItem (index) { const newIncList = this.state.incomeItems; const slicedIncome = newIncList.slice(0, index).concat(newIncList.slice(index + 1)); this.setState({incomeItems: slicedIncome}); let total = 0; slicedIncome.map((inc) => {total += parseInt(inc.amount)}); this.setState({totalIncome: total}); } deleteExpenseItem (index) { const newExpList = this.state.expenseItems; const slicedExp = newExpList.slice(0, index).concat(newExpList.slice(index + 1)); this.setState({expenseItems: slicedExp}); let total = 0; slicedExp.map((exp) => {total += parseInt(exp.expAmount)}); this.setState({totalExpense: total}); } render() { return ( <div className="App"> <header className="App-header"> <h1 className="App-title">Monthly Budget</h1> </header> <div className="container"> <AddItem addBudgetItem={this.addBudgetItem} addExpenseItem={this.addExpenseItem}/> <div className="line"></div> <div className="UIdiv"> <table> <h1>INCOME ITEMS</h1> <tr><IncomeList incomeList={this.state.incomeItems} deleteIncomeItem={this.deleteIncomeItem}/></tr> <p className="income-desc">Total Income: {this.state.totalIncome}</p> </table> <table> <h1>EXPENSE ITEMS</h1> <tr><ExpenseList expenseList={this.state.expenseItems} deleteExpenseItem={this.deleteExpenseItem}/></tr> <p className="expense-desc">Total Expense: {this.state.totalExpense} </p> </table> <h2 style={(this.state.totalIncome - this.state.totalExpense === 0) ? {color: 'black'}: (this.state.totalIncome > this.state.totalExpense) ? {color:'green'}:{color:'red'}}> TOTAL BALANCE: {this.state.totalIncome - this.state.totalExpense}</h2> </div> </div> <div> <Chart chartData={this.state.chartData}/> </div> </div> ); } } export default App; //Child Component - Chart import React from 'react' import {Doughnut} from 'react-chartjs-2'; class Chart extends React.Component { constructor(props){ super(props); this.state = { chartData: props.chartData } } render(){ return ( <Doughnut data={this.state.chartData} width={100} height={50} /> ) } } export default Chart 是否在设备上存在。如果没有,我使用RNFetchBlob和对象的参数device_path将映像下载到设备。之后,我将对象的download_url更新为新下载的图像。

执行以下代码时,我的函数device_path返回checkPaths。我希望函数返回此值:

{"_40":0,"_65":0,"_55":null,"_72":null}

我应该如何修改我的功能以使其正常工作?

[
  { device_path: 'goodimagepath1', download_url: 'mysecretdownloadurl1' },
  { device_path: 'goodimagepath2', download_url: 'mysecretdownloadurl2' }
];

1 个答案:

答案 0 :(得分:0)

由于checkPaths是异步的,因此它返回一个promise。应该在componentDidMount中进行处理,如下所示:

checkPaths(this.image_references).then(checked_paths => {
      console.log("resolved promise", checked_paths)
      console.log("checked image paths", JSON.stringify(checked_paths));
    }).catch(e => {
      console.log("error checking image paths", e)
    });

我还修改了功能checkPaths,以等待检查图像路径并等待下载图像。

如果有更干净的方法可以做到这一点,我就耳熟能详。

import React, { Component } from "react";
import { View, Text } from "react-native";
import RNFetchBlob from "rn-fetch-blob";

async function checkPaths(image_metadata_list) {

  const promises = image_metadata_list.map(async (image_metadata, idx) => {

    const exists = await RNFetchBlob.fs.exists(image_metadata.device_path)

    if (exists === false) {
      console.log("image does not exist on device, downloading...");
      const dirs = RNFetchBlob.fs.dirs;
      const filename = (idx + 1).toString() + '.jpg'

      const resp = await RNFetchBlob.config({
        path: dirs.DocumentDir + `/user_images/${filename}`
      }).fetch('GET', `${image_metadata.download_url}`).progress((received = 0, total = 0) => {
        //Handle progress of download here.. May be update UI...\
      }).then((resp) => {
        // update the device path
        image_metadata.device_path = resp.path();
        console.log("image path modified", image_metadata);
      }).catch(e => {
        console.log("error downloading image", e);
      })
    }
    else {
      console.log("image path OK", image_metadata);
    }
    return image_metadata;
  })
  return await Promise.all(promises);
}


export default class App extends Component {
  constructor(props) {
    super(props);
    this.image_references = [
      { device_path: 'badimagepath1', download_url: 'https://firebasestorage.googleapis.com/v0/b/fivedates-dev.appspot.com/o/user_images%2FoHK9DQ94ZZOBIejbVO8luJZnEU22%2F1.jpg?alt=media&token=6c5e053d-45b4-4ab0-a52b-65c1180624ed' },
      { device_path: 'badimagepath2', download_url: 'https://firebasestorage.googleapis.com/v0/b/fivedates-dev.appspot.com/o/user_images%2FoHK9DQ94ZZOBIejbVO8luJZnEU22%2F1.jpg?alt=media&token=6c5e053d-45b4-4ab0-a52b-65c1180624ed' }
    ];
  }
  componentDidMount() {
    console.log("component mounted");
    console.log("checking image paths", JSON.stringify(this.image_references));

    checkPaths(this.image_references).then(checked_paths => {
      console.log("resolved promise", checked_paths)
      console.log("checked image paths", JSON.stringify(checked_paths));
    }).catch(e => {
      console.log("error checking image paths", e)
    });
  }
  render() {
    return (
      <View style={{ flex: 1 }}>
        <Text>Welcome to MWE</Text>
      </View>
    )
  }
}