Scenario
In the actual business development, there are often some tasks that need to be executed for a long time, so there are two problems:
- Frontend: How to realize the display and step of progress bar?
- Backend: If the backend takes too long to execute, the frontend will receive a timeout error. How to avoid it?
Module a-progress
easily solves the above problems, and has the following characteristics:
- Convenient API
- Support multi-level progress bar
Preview
Frontend
src/suite-vendor/test-party/modules/test-party/front/src/kitchen-sink/pages/progress.vue
onPerformStart() {
return new Promise((resolve, reject) => {
return this.$api.post('test/feat/progress').then(data => {
const progressId = data.progressId;
this.$view.dialog.progressbar({ progressId, title: this.$text('Working') }).then(data => {
console.log(data);
resolve();
}).catch(err => {
console.log(err);
reject();
});
});
});
},
- Firstly, perform backend API route to get
progressId
- Then invoke
$view.dialog.progressBar
to display the progress bar. This function automatically gets the latest progress from the backend and updates the display
Backend - API Route
src/suite-vendor/test-party/modules/test-party/backend/src/routes.js
// test/feat/progress
{ method: 'post', path: 'test/feat/progress', controller: testFeatProgress, middlewares: 'progress', meta: { auth: { enable: false } } },
{ method: 'post', path: 'test/feat/progressInBackground', controller: testFeatProgress, middlewares: 'inner,progress', meta: { auth: { enable: false } } },
Backend - Controller
src/suite-vendor/test-party/modules/test-party/backend/src/controller/test/feat/progress.js
module.exports = app => {
class ProgressController extends app.Controller {
async progress() {
// create progress
const progressId = await this.ctx.meta.progress.create();
// background
this.ctx.performActionInBackground({
method: 'post',
url: 'test/feat/progressInBackground',
body: {
progressId,
},
});
// return progressId
this.ctx.success({ progressId });
}
async progressInBackground() {
const progressId = this.ctx.request.body.progressId;
try {
// level one
await this._levelOne({ progressId, progressNo: 0 });
// progress done
await this.ctx.meta.progress.done({ progressId, message: this.ctx.text('Well Done') });
// ok
this.ctx.success(true);
} catch (err) {
// progress error
await this.ctx.meta.progress.error({ progressId, message: err.message });
// throw err
throw err;
}
}
async _levelOne({ progressId, progressNo }) {
const total = 2;
let current = 0;
for (let i = 0; i < total; i++) {
const text = `${this.ctx.text('Level One')}: ${i + 1}`;
await this.ctx.meta.progress.update({
progressId,
progressNo,
total,
progress: current++,
text,
});
// sleep
await this.ctx.meta.util.sleep(1500);
// level two
await this._levelTwo({ progressId, progressNo: progressNo + 1 });
}
}
async _levelTwo({ progressId, progressNo }) {
const total = 2;
let current = 0;
for (let i = 0; i < total; i++) {
const text = `${this.ctx.text('Level Two')}: ${i + 1}`;
await this.ctx.meta.progress.update({
progressId,
progressNo,
total,
progress: current++,
text,
});
// sleep
await this.ctx.meta.util.sleep(1500);
// level two
await this._levelThree({ progressId, progressNo: progressNo + 1 });
}
}
async _levelThree({ progressId, progressNo }) {
const total = 3;
let current = 0;
for (let i = 0; i < total; i++) {
const text = `${this.ctx.text('Level Three')}: ${i + 1}`;
await this.ctx.meta.progress.update({
progressId,
progressNo,
total,
progress: current++,
text,
});
// sleep
await this.ctx.meta.util.sleep(1500);
}
}
}
return ProgressController;
};
Three levels of progress bar are implemented here, and for the sake of intuitiveness, the common code of these three levels is not refined into a common function. In the actual development, it can be simplified according to the actual needs
Description of Process
-
Method:
progress
- invoke
ctx.meta.progress.create
to create aprogressId
- invoke
ctx.performActionInBackground
to start the task as the background mode - return
progressId
to the frontend for displaying the progress bar
- invoke
-
Method:
progressInBackground
- Use
try/catch
structure to wrap code, so as to catch code exceptions and update the status of progress bar - invoke
ctx.meta.progress.update
to update the progress - invoke
ctx.meta.progress.done
to complete the progress - invoke
ctx.meta.progress.error
to raise error message
- Use
Description of API
- Method:
ctx.meta.progress.update
Name | Description |
---|---|
progressId | progress Id |
progressNo | the level index, start from 0 |
total | the total tasks of current level |
progress | the task index of current level, start from 0 |
text | description of the current task |
- Method:
ctx.meta.progress.done
Name | Description |
---|---|
progressId | progress Id |
message | description on completion |
- Method:
ctx.meta.progress.error
Name | Description |
---|---|
progressId | progress Id |
message | error description |
Comments: