Asynchronous programming using Hooks

Keywords: Front-end Programming JSON network Javascript

This excerpt is from Rax's official website rax.js.org

introduce

Javascript is a single-threaded programming language. A single-threaded feature is that it can only handle one thing at a time, and the time-consuming execution of the current code task can block subsequent code execution.Asynchronous programming is an event-driven programming in which the caller is notified by status, notification, and callbacks when a function or method is requested and can continue to perform other tasks without immediately waiting for a response.

Asynchronous programming method

Asynchronous programming methods in js include callback functions, event handling functions, observers, Promise, Generator, async, etc. Next, look at the common asynchronous programming methods used in Rax.

callback

import { createElement, render, useState, useEffect } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';

function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    setCount(count + 1);
  }, []);
  return (
    <View>
      <Text >Hello Rax {count}!</Text> 
    </View>
  );
}

export default App;
//Copy Code

We pass in a callback in the effect hook useEffect, call it when the component mount s, set the count, and use the state hook to update the local state.This is a common way to use callbacks in Rax.

Event Handler

import { createElement, render, useState, useEffect } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';

function App() {
  const [count, setCount] = useState(1);

  function showAlert() {
    setTimeout(() => {
      alert('You clicked on: ' + count);
    }, 3000);
  }

  return (
    <View>
      <Text onClick={() => setCount(count + 1)}>Add count: You clicked {count} times</Text> 
      <Text onClick={showAlert}>Hello Rax,show alert!</Text> 
    </View>
  );
}

export default App;
//Copy Code

If we follow these steps:

  • Click to increase count to 2
  • Click show alert
  • Click Increase count to 3 now

The count value that alert pops up is still 2.Alert gets the state of count on click, which is called each time the component function renders, but the count value is constant in each call and assigned to the state value in the current rendering.In fact, the same is true for normal functions. If a function is called several times to pass in different parameters, then each call to the function will also take in the parameter value passed in.

Promise

import { createElement, render, useState, useEffect } from 'rax';
import request from 'universal-request';
import Text from 'rax-text';

function App() {
  const [value, setValue] = useState(1);

  useEffect(() => {
    function getValue() {
      request({
        url: 'https://httpbin.org/post',
        method: 'POST',
        headers: {
          'Access-Control-Allow-Origin': '*'
        },
        data: {
          value: 'Rax'
        },
        timeout: 5000
      }).then((result) => {
        const data = JSON.parse(result.data.data);
		// setValue
        setValue(data.value);
      }).catch((error) => {
      });
    }
    getValue();
  }, []);

  return (
    <Text>Current value: {value}</Text> 
  );
}

export default App;
//Copy Code

An example of a network request is a good illustration of how Promise works, sending a request after the first mount, changing the local state after the data is obtained, and triggering a render again.Promise also solves the problem of callback to Hell and is friendly to concurrent execution.When we have a lot of asynchronous operations, we find that we need to keep writing useEffect and so on, which increases the amount of code, so we can pull out a custom hook and get only the data we care about.

import { useEffect, useState } from 'rax';

export default function usePromise(promise) {
  const [error, setError] = useState(null);
  const [result, setResult] = useState(null);

  useEffect(
    () => {
      let canceled = false;

      promise
        .then(r => {
          if (!canceled) {
            setResult(r);
          }
        })
        .catch(e => {
          if (!canceled) {
            setError(e);
          }
        });

      return () => {
        canceled = true;
      };
    },
    [promise]
  );

  return [result, error];
}
//Copy Code

Custom hook usePromise takes promise as a parameter and handles component destruction, usePromise has been published as npm package rax-use-promise.When we use the network request again, we just need to call usePromise and get the returned data and error.

import { createElement, render,  useState, useEffect, useMemo } from 'rax';
import usePromise from 'rax-use-promise';
import request from 'universal-request';
import Text from 'rax-text';

const getValue = () =>request({
  url: 'https://httpbin.org/post',
  method: 'POST',
  headers: {
	'Access-Control-Allow-Origin': '*'
  },
  data: {
	value: 'Rax'
  },
  timeout: 5000
}).then(result => JSON.parse(result.data.data));

function App() {
  const [data, error] = usePromise(useMemo(getValue));
  return (
    <Text>Current value: {data.value}</Text> 
  );
}

export default App;
//Copy Code

Reference resources

Hooks

rax-use-promise


Author: Baboon 48k
Link: https://juejin.im/post/5de527165188255a71417173
Source: Excavation
Copyright belongs to the author.For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.

Posted by Trafalger on Sat, 07 Dec 2019 04:19:10 -0800