Background:

When building a front-end framework, you need to customize the prompt box. I started to check the source code of MessageBox. In the process of combing the source code, I found that Promise was used in MessageBox. When we use the prompt code, we can add then and catch after the function to handle the callbacks to the ok and cancel buttons, and we can be sure that we use the Promise object, no doubt about it. But how does it happen that the then or catch callback is only triggered when the button is clicked? With this question in mind, I began to comb through the source code of the MessageBox component.

MessageBox component file composition:

  1. Index.js file: Export MessageBox object, actually export MessageBox object in main.js, you can directly view the SRC /main.js file
  2. SRC /main.js: This file is the core file that defines the MessageBox object. It is not object-oriented programming, so it sets alert, Confirm, and Prompt prompt boxes directly on the MessageBox object.
  3. SRC /main.vue: this component mainly provides the VNODE of the prompt box and the logic of closing the prompt box

By imitating SRC /main.js to customize alert, confirm and Prompt prompt boxes in MessageBox, we can complete the task. But if you want to know how it works, you can only continue to explore.

The key code

For the first time, I had a general understanding of the overall code. In the process of sorting out, I found the definition of MessageBox function object, and there was a code in it that caught my attention, such as code section 1:

 return new Promise((resolve, reject) = > { // eslint-disable-line

   msgQueue.push({

​    options: merge({}, defaults, MessageBox.defaults, options),

​    callback: callback,

​    resolve: resolve,

​    reject: reject

   });
Copy the code

In this code, we refer to resolve and reject as attributes of objects, rather than resolve() or reject() as we used before, and msgQueue is an array queue that holds newly formed objects. It can be inferred that msgQueue stores the configuration information of the prompt box, since there may be multiple prompt boxes. When do resolve and Reject trigger calls? But it’s almost certain that when resolve and reject execute, that’s when we bind our own then and catch callbacks.

Call the code that executes resolve and reject:

The SRC /main.js file defines defaultCallback to perform resolve, as shown in code 2:

 if (action === 'confirm') {

​    if (instance.showInput) {

​     currentMsg.resolve({ value: instance.inputValue, action });

​    } else{ currentMsg.resolve(action); }}else if (currentMsg.reject && (action === 'cancel' || action === 'close')) { // If the user clicks the cancel button, the value of the cancel button is passed to the catch function

​    currentMsg.reject(action);

   }
Copy the code

The confirm, Cancel, and close key fields appear. These key fields are available in our bound then and catch callbacks. This is done by clicking OK to execute the callback in THEN and clicking cancel to execute the callback in Catch. The implementation principle is not complicated, but it comes down to a good grasp of the underlying principle of code.

Extended thinking:

  1. You’ve probably come across JavaScript code that defines thread suspension before, in paragraph 3:
function sleep(time){

 return new Promise(function(resolve,reject){

  setTimeout(resolve,time)

 })
}
async function main(){
  await sleep(5000)
  console.log('hello world')}Copy the code

The result of execution is “Hello World” printed after 5 seconds and since the JavaScript engine is single-threaded it can be suspended. SetTimeout delays the execution of resolve in the same way that MessageBox resolve is referenced by another object. Ordinary people encounter this code is a simple memory, cattle will be the principle behind this code analysis. Salute to Daniel!!

Ideas for constructing MessageBox components:

Before a big bull said, “thinking is king”, this sentence is absolutely correct. Now that the core problems of MessageBox have been clarified, let’s continue to sort out the overall construction ideas of MessageBox components.

First, this is what we usually do when we use it, as in code 4:

open() {

 this.$confirm('This operation will permanently delete the file. Do you want to continue? '.'tip', {

   confirmButtonText: 'sure'.cancelButtonText: 'cancel'.type: 'warning'

  }).then(() = > {

   this.$message({

​    type: 'success',

​    message: 'Deleted successfully! '

   });

  }).catch(() = > {

   this.$message({

​    type: 'info',

​    message: 'Cancelled delete'

   });

  });

}

Copy the code

Then a prompt box appears on the page:

$confirm() this.$confirm() The function defined in SRC /main.js returns the result of the execution of the MessageBox function, and if Promise is supported, returns a Promise object. If Promise is not supported, null is returned, and then cannot be used.

MessageBox encapsulates the MessageBox triggered by the user into a new object and saves it to the msgQueue queue. This function does not pop up the prompt immediately, as shown in snippet 1.

The MessageBox function is executed at the same time as the showNextMsg function, which is used to pop up the MessageBox and queue the msgQueue objects to perform the popup.

How does popover work? Take a look at the following code, code segment 5:

import msgboxVue from './main.vue';
const MessageBoxConstructor = Vue.extend(msgboxVue);
Copy the code

In the Vue framework, Vue components are also functions. The vue.extend method creates the component’s constructor, which makes it possible to create a new component-based instance object, as shown in section 6:

const initInstance = () => {

 instance = new MessageBoxConstructor({

  el: document.createElement('div')

 });
 instance.callback = defaultCallback;

};
Copy the code

The visible property is listened for in the main.vue component. The instance object created in main.js is bound to the Visible property. This can control the display and hide of the prompt box.

Finally, when the user clicks on all the buttons in the prompt, the prompt is hidden and the this.doclose () method is called in main.vue, This method calls this.callback(), which in turn calls this.defaultcallback (), which triggers the then or catch callback.

The overall construction flowchart is as follows:

In conclusion, the basic ability of code programming is important, but if you just stay at the level of API calls, you can’t expand your ability. Looking at other people’s code is about thinking, then syntax. Looking at someone else’s code can be time-consuming, especially without any comments. The way I do it is I guess, and then I go to the code and check it out. Look at the source code do not need to care too much about the details, first comb clear.

Please look forward to an article summarizing and analyzing the use of Promise.