5
头图

The boss has come to BT again😳

Our company recently developed a todo management product, vue3+axios, and this is the case.

Boss: I tried the beta version of our product, and the overall implementation is good, but...

Me: 😨😨😨

Boss: The experience needs to be optimized. For example, can the data be displayed instantly when the todo list page is turned? Can you stop waiting when adding and editing todos?

I (thinking): ❓❓❓ This is to skip the interaction with the server? I can't get it right!

Boss: Young man, look good on you, can you publish a version tomorrow for me to see?
me: I...I try!

I suddenly got smart

For the problem of displaying data instantly when turning pages, can we request the current page data first, and then make a cache to preload the next page data, just do what we say, the code is probably like this:

 // todo列表组件
const currentPage = ref(1);
const pageCache = {};
const loading = ref(false);

// 如果有缓存则返回缓存,没有则请求数据并缓存
const getPageData = async page => {
    let pageData = pageCache[page];
    if (!pageData) {
        loading.value = true;
        pageData = await axios.get('...', {
            params: {
                page: page,
                pageSize: 10,
            }
        });
        loading.value = false;
        pageCache[page] = pageData;
    }
    return pageData;
};

// 进入时请求当前页数据,同时预加载下一页数据
const todoList = ref([]);
const loadNextPage = async () => {
    const pageData = await getPageData(currentPage.value);
    todoList.value.push(pageData);
    currentPage.value++;
    getPageData(currentPage.value);
};
onMounted(loadNextPage);
window.addEventListener(() => {
    if (/* 判断滑动到最底部... */) {
        loadNextPage();
    }
});

For the problem of not waiting for adding and editing todo, pass the update event over, and then I directly update optimistically

 // 编辑todo组件
const addTodo = newTodoData => {
    axios.post('...', newTodoData).then().then(newId => {
        // 响应后将原todo项替换为带id的项
        this.$emit('replaceTodo', {
            search: newTodoData,
            replacement: {
                id: newId,
                ...newTodoData,
            }
        });
    });
    
    // 先立即添加到todoList
    this.$emit('addTodo', newTodoData);
    alert('提交成功');
}

It seems that everything is so perfect, the boss should praise me.

I really emo 😓

Boss: Boy, you did a good job, just...

Me: 😲😲😲

Boss: My network was not very good just now. It showed that the submission was successful, but it didn't seem to be really successful. It was not very stable. . .

Me: Good boss, I'll go back and have a look😔😔😔

Boss: By the way, it would be better if it can be used without internet.

Me: Good boss! 😀😀😀 (Mind: What???🤬🤬🤬)

What's up! ! ! ?

After some intense discussions and baptisms, we finally came up with a plan, we are going to:

  1. Let the request information without successful request be saved to the local first, and then wait for a certain period of time
  2. Save the request information directly to the local when offline, and then submit it when connected to the Internet

😎😎😎 Perfect! ! !

 // 代码有点长,自行脑补...

SB boss is back

Boss: Haha, it seems to be much better than before. Can you use your caching solution for the points function, skin function, and order function?

Me: 🤢🤢🤢

Boss: Oh yes, we will have a pad version in the future...

💀💀💀 Well, there is no other way, after all, I have not escaped the encapsulation step.

We decided to encapsulate it into a library

Front-end team leader: Oh, you've worked hard, I'll leave this to you. Since we want to make a js library, then we have to think about these issues.

  1. How to abstract to cover more scenarios?
  2. Can a front-end novice be able to get started quickly?
  3. There are many and complicated states related to requests. Can they be managed uniformly?
  4. The company may have react projects in the future, can they be compatible together?
  5. The written library should not be too large

Me: Good team leader, this is also a challenge for me. Can I apply for a good design for two months? 🤨🤨🤨

Front-end team leader: Okay, let's do it, boy! ! ! 😚😚😚

But it was really torturous and challenging, with so many conditions to support. After scratching my head and thinking for a while, the result I got is: my head is getting colder and colder😶😶😶, but still, keep going! ! !

I came up with a concept for request scene management

After a lot of hard work, I finally handed over a draft, and I came up with a concept of request scene management . What is request scenario management? Probably so.

We always run into these issues when making a request:

  1. when the request was made;
  2. Whether to display the request status;
  3. Whether to encapsulate it into a request function for repeated calls;
  4. how to process the response data;
  5. Whether to cache frequently used response data;
  6. How to operate data across pages;
  7. Can I still submit data offline?
  8. ...

And fetch or axios tend to focus more on how to interact with the server, but we always need to deal with the above problems by ourselves. These functions are beneficial to application performance and stability. Allows programmers to write low-maintenance code. The request scene management is to abstract all the links from the preparation of the request to the completion of the response data processing, so as to cover the model of the entire CS interaction life cycle from the perspective of the front end.

CS interaction: refers to all client types and server-side data interaction

Come, go directly to the model diagram.

185773583-a884e1ed-7507-4e96-9030-f20aa557eb5a.png

alova was born

According to the logic of request scene management, we have completed this js library named alova , which is like a request library's armed armor, helping us to use the request library to initiate requests, and at the same time in the form of responsive state To manage request-related data, we position it as a supplement to the request library such as axios , not a replacement.

Haha, I did all this! ! ! 🤣🤣🤣

  1. ✅Abstract covers more scenes
  2. ✅Axios similar API, front-end novice can get started quickly
  3. ✅Silent submission, offline submission
  4. ✅The various states related to the request are unifiedly managed
  5. ✅Compatible with the company's current vue project, and also compatible with the company's subsequent react projects
  6. ✅3+kb after compression

Of course, the function is much more than that! ! ! And these:

  1. ✅ Non-async mode of requests
  2. ✅Response data caching
  3. ✅Data pre-fetch
  4. ...

The alova library portal is here! ! ! , please don't be ignorant, click start 🤣🤣🤣

Then our todo list display can be changed to this.
First create an alova instance, is it very similar to creating an axios instance?

 // api/index.js
export const alovaInstance = createAlova({
    baseURL: 'https://api.alovajs.org',
    
    // vue项目传入VueHook,react项目传入ReactHook
    statesHook: VueHook,
    
    // 传一个请求适配器,GlobalFetch是我们提供的fetch api适配器
    // 你想用axios也可以自定义一个适配器
    requestAdapter: GlobalFetch(),
    
    // 是不是有熟悉的味道
    beforeRequest(config) {
        config.headers.token = 'tokenxxx';
    },
    async responsed(response) {
      const json = await response.json();
      if (json.code !== 200) {
        throw new Error(json.message);
      }
      return json.data;
    },
});

Define the request function.

 // api/todo.js
// 创建请求对象
export const getTodoList = page => alovaInstance.Get('...', {
    params: {
        page,
        pageSize: 10,
    },
    localCache: 50000,
});

Finally, the request is made in the component.

 // TodoList.vue
const currentPage = ref(1);
const todoList = ref([]);

// 创建预加载器
const { fetch } = useFetcher();

const {
    loading,
    data: pageData,
    error,
    onSuccess,
    
    // 监听currentPage变化就去触发请求
} = useWatcher(() => getTodoList(currentPage.value), [currentPage], {
    immediate: true
});
onSuccess(rawPageData => {
    todoList.value.push(rawPageData);
    
    // 请求成功后预加载下一页数据,并缓存
    fetch(getTodoList(currentPage.value + 1));
});

window.addEventListener(() => {
    if (/* 判断滑动到最底部... */) {
        // 页码改变,自动发起请求,然后命中缓存并立即调用onSuccess
        currentPage.value ++;
    }
});

There is no need to wait for the creation of the todo item of the network. After the silent mode is turned on, it can still be completed normally in the offline state.

Create a request function definition for todo

 // api/todo.js
// 创建请求对象
export const createTodo = newTodo => alovaInstance.Post('...', newTodo);

A silent commit occurs after clicking the create button.

 const newTodo = reactive({
    title: '',
    time: '',
});


const {
    send: requestCreateTodo
    onSuccess
} = useRequest(() => createTodo(newTodo), {
    // 设置不立即发出请求,而是改用send函数调用发起,即手动模式
    immediate: false,
    
    // 设置为静默提交模式
    silent: true,
});

// 静默提交时,成功回调将会被立即执行
onSuccess(() => {

    // 在这里手动更新新的todo项到todoList里
    updateState(getTodoList(), todoList => {
        return [
            ...todoList,
            {
                // 看到这了没?🤩🤩🤩,这是延迟更新数据的写法
                '+id': resData => resData.id,
                ...newTodo,
            }
        ]
    });
});


// 假设点击“创建”按钮后触发此函数
const handleCreateTodoBtnClick = () => {
    requestCreateTodo();
};

In this way, the operation of silent submission is completed. In the figure, there is a function of delaying data update . I want to explain it (emphasis 🖍🖍🖍), it is like a placeholder, which can make the determined data update immediately To the corresponding reactive state, let the interface re-render immediately, and then replace the placeholder with the actual data after requesting the response later.

In the example, the todo item is immediately updated to the todo list data when the todo item is created, and its id will be automatically replaced with the actual id after the submission is successful, thus achieving non-delayed data submission.

😃This time, our boss is finally happy!

Then, we took some time to use multiple ends of the project alova to transform, all achieved good results, and we all laughed! ! ! Especially the boss 🧔🧔🧔.

Boss: Young man, you did a great job. I want to give you a medal. Our product experience has gone up a notch compared to before!

Me: 😶😶😶Boss, don't be impulsive! ! ! Or... just send me an extra 20,000 bonus...

Boss: You are thinking about the fart! ! ! 😲😲😲

Front-end team leader: You're thinking about ass! ! ! 😲😲😲

Me: Just kidding, just let me be the team leader🤭🤭🤭

Front-end team leader: I...qnmlgb!

Ladies and gentlemen, what do you think of this idea? Let me see your hands 🙌🏻🙌🏻🙌🏻

Again, the alova library portal is here! ! ! , please don't be ignorant, click start 🤣🤣🤣


爱编程的小金
39 声望7 粉丝

爱研究各种技术的小金