1. Introduction

Goethe said: reading a good book, is talking with noble people.

In the same way, reading the source code of a good open source project is like talking to the big cheese.

I always felt that reading source code is a great thing, is only the big guy will do. In fact, the source code is not so difficult to imagine, at least there are a lot of read understand. For example, the tool function in the source code, even the primary front-end development is also able to understand. The important thing is, to take this step, there’s nothing wrong with reading the source code.

Reading this article, you will learn:

1. Debugging skills and tools of javascript and NodeJS; 2. How to learn to debug AXIOS source code; 3. How to learn the code of excellent open source project and apply it to my own project; 4. Axios source code utility functions;Copy the code

2. Prepare the environment

2.1 Read the contribution guide for open Source projects

Open up axios and you’ll be surprised to see that it opens vscode in your browser. Yes, you have vscode open in your browser, and you have axios source open as well. If you look closely at the URL in your browser’s address bar, you’ll notice that github has an extra 1s after it opens a project on Github. A small extension: add 1s to each github url to view the source code in the web version of vscode.

For open source projects, contribution guidelines can generally be found in the readme. md file at root or in CONTRIBUTING. The contribution guide explains some considerations for participating in contributing code, such as: code style, code submission comment format, development, debugging, etc.

Opening up CONTRIBUTING. Md, you can see line 54:

Running sandbox in browser ' 'bash $NPM start # Open 127.0.0.1:3000Copy the code

This is how to run the project in the browser.

2.2 Clone the project and run it

The version using AXIos here is v0.24.0;

Git clone https://github.com/axios/axios.git CD axios NPM start open http://localhost:3000/Copy the code

You will see a page like this:

Open your browser’s console, select the Source option, and find the source in the Axios directory, as shown below:

The axios.js file is the entry file, and you can debug at any point you want.

In fact, the process of reading all the source code is similar, the reason for saying so detailed, is to be able to let students who have not read the source code can also follow the step by step reading up. When you read, there will be a lot of harvest, record the process and harvest, slowly improve themselves, sooner or later become a big man.

3. Utility functions

Today’s hero is the utils.js file, in which the utility functions are listed below:

3.1 isArrayJudge array

var toString = Object.prototype.toString; // The type of each object can be obtained by 'toString()'. Function isArray(val) {return tostring. call(val) === '[object Array]'; }Copy the code

3.2 isUndefinedjudgeUndefined

Typeof null === 'object' function isUndefined(val) {return typeof val === 'undefined'; }Copy the code

3.3 isBufferjudgebuffer

// check whether 'undefined' and 'null' exist. Function isBuffer(val) {return val! Function isBuffer(val) {return val! == null && ! isUndefined(val) && val.constructor ! == null && ! isUndefined(val.constructor) && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val); }Copy the code

What is the Buffer?

The JavaScript language itself only has string data types, not binary data types.

But when dealing with things like TCP streams or file streams, you must use binary data. Therefore, in Node.js, a Buffer class is defined to create a Buffer dedicated to binary data. Details can be found in the official documentation or in a more accessible explanation.

Because Axios can run in a browser and node environment, nodeJS knowledge is used internally.

3.4 isFormDatajudgeFormData

Function isFormData(val) {return (typeof FormData!) function isFormData(val) {return (typeof FormData! == 'undefined') && (val instanceof FormData); Function C() {} function D() {} const C = new C() C instanceof C True because object.getProtoTypeof (c) === c. prototype c instanceof Object // output: True for the Object. The prototype. IsPrototypeOf (c) instanceof D/c/output: false because D.p rototype is not on the prototype chain of cCopy the code

3.5 isObjectJudge object

Function isObject(val) {return val! == null && typeof val === 'object'; }Copy the code

3.6 isPlainObjectJudge pure object

Pure objects: Objects created with {} or new Object().

function isPlainObject(val) { if (Object.prototype.toString.call(val) ! == '[object Object]') { return false; } var prototype = Object.getPrototypeOf(val); return prototype === null || prototype === Object.prototype; } // example 1 const o = {name: 'jay} isPlainObject(o) // true // example 2 Const o = new Object() o.Name = 'jay' isPlainObject(O)  {} const c = new C() isPlainObject(c); // false // Check whether the Object's prototype is' null 'or' object.prototype 'Copy the code

3.7 isDatejudgeDate

function isDate(val) {
  return Object.prototype.toString.call(val) === '[object Date]';
}
Copy the code

3.8 isFileDetermine the file type

function isFile(val) {
  return Object.prototype.toString.call(val) === '[object File]';
}
Copy the code

3.9 isBlobjudgeBlob

function isBlob(val) {
  return Object.prototype.toString.call(val) === '[object Blob]';
}
Copy the code

A Blob object represents an immutable, raw data-like file object. Its data can be read in text or binary format.

3.10 isFunctionJudging function

function isFunction(val) {
  return Object.prototype.toString.call(val) === '[object Function]';
}
Copy the code

3.11 isStreamCheck whether it is a stream

Function isStream(val) {return isObject(val) &&isfunction (val.pipe); }Copy the code

3.12 isURLSearchParamsjudgeURLSearchParams

function isURLSearchParams(val) { return typeof URLSearchParams ! == 'undefined' && val instanceof URLSearchParams; } // example const paramsString = "q= urlutils. searchParams&topic= API "const searchParams = new URLSearchParams(paramsString);  isURLSearchParams(searchParams) // trueCopy the code

The URLSearchParams interface defines some useful methods for handling query strings for urls, as described in MDN:

var paramsString = "q=URLUtils.searchParams&topic=api" var searchParams = new URLSearchParams(paramsString); for (let p of searchParams) { console.log(p); } // Output ['q', 'urlutils.searchParams'] ['topic',' API '] searchParams.has("topic") === true; // true searchParams.get("topic") === "api"; // true searchParams.getAll("topic"); // ["api"] searchParams.get("foo") === null; // true searchParams.append("topic", "webdev"); searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev" searchParams.set("topic", "More webdev"); searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev" searchParams.delete("topic"); searchParams.toString(); // "q=URLUtils.searchParams"Copy the code

3.13 trimRemove leading and trailing Spaces

// If 'trim' does not exist, use the regular function trim(STR) {return str.trim? str.trim() : str.replace(/^\s+|\s+$/g, ''); }Copy the code

3.14 isStandardBrowserEnvDetermine the standard browser environment

function isStandardBrowserEnv() { if (typeof navigator ! == 'undefined' && (navigator.product === 'ReactNative' || navigator.product === 'NativeScript' || navigator.product === 'NS')) { return false; } return ( typeof window ! == 'undefined' && typeof document ! == 'undefined' ); }Copy the code

But the use of this property is no longer officially recommended.

3.15 forEachIterate over an object or array

Keep English notes to improve your English reading ability.

Iterate over an Array or an Object invoking a function for each item. ** Iterate over an Array or an Object invoking a function for each item ** If 'obj' is an Array Callback will be called passing * the value, index, and complete array for each item. * * If 'obj' is an Object callback will be called passing * the value, key, And complete object for each property. The callback is going to call value, key, And The entire Object * * @ param {Object | Array} obj The Object to iterate * @ param Function fn attach The callback to invoke for each item * / Function forEach(obj, fn) {// Don't bother if no value provided Don't need to deal with the if (obj = = = null | | typeof obj = = = 'undefined') {return; } // Force an array if not already something iterable // If (typeof obj! == 'object') { obj = [obj]; } if (isArray(obj)) {// Iterate over array values // Iterate over array values, for loop fn for (var I = 0, l = obj.length; i < l; i++) { fn.call(null, obj[i], i, obj); }} else {// Iterate over object keys // For (var with a for loop execution callback fn key in obj) {/ / traversal can be enumerated attribute only if (Object. The prototype. The hasOwnProperty. Call (obj, key)) {fn. Call (null, obj[key], key, obj); }}}}Copy the code

So, why not use forEach and for… in… ???????

3.16 stripBOMdeleteUTF-8In the encodingBOM

/**
 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
 *
 * @param {string} content with BOM
 * @return {string} content value without BOM
 */
 
function stripBOM(content) {
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return content;
}
Copy the code

BOM, short for Byte Order Mark, is a Unicode character that appears at the beginning of text and identifies the Byte Order. The main advantage of UTF-8 is ASCII compatibility, but this benefit is lost when BOM is used.

4. To summarize

This article mainly introduces the debugging process of AXIos source code, and introduces some very useful utility functions in utils.js. I believe that through reading the source code, accumulated over a long period of time, and the code or ideas applied to their own projects, I believe that can improve their coding ability.

come on! worker!

Some useful tools are also recommended:

Run in a browservscode, view the source code

Sandbox code that runs multiple languages and can add dependencies

Vs Code Runner plugin