Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

Adapter model is also known as a wrapper, converting the interface of one class to another interface to meet the needs of users, mainly in order to solve the problem of interface is incompatible between objects, such as iterative upgrade as business the old interface interface is not compatible with heart, this time can’t be forced to use old interface users to upgrade, but add an adapter in the middle, In daily life, adapter cases can be seen everywhere, such as the disunity of headphone jack and charging interface. At this time, an adapter is needed to solve the problem

UML:

Take a look at the corresponding UML code implementation:

class Target {
    constructor(type) {
        let result;

        switch (type) {
            case "adapter":
                result = new Adapter();
                break;
            default:
                result = null;
        }
        return result;
    }

    Request() {
            console.log('Target Request'); }}class Adaptee {
    constructor() {
        console.log("Adaptee created");
    }

    SpecificRequest() {
        console.log("Adaptee request"); }}class Adapter extends Adaptee {
    constructor() {
        super(a);console.log("Adapter created");
    }

    Request() {
        return this.SpecificRequest(); }}function init_Adapter() {
    var f = new Target("adapter");
    f.Request();
}

init_Adapter();
Copy the code

Application scenarios

Axios supports node and browser, so calling axios on different ends requires different processing, which is insensitive to the user. We use the same SET of apis to do things directly, and we don’t care what is done inside. At this point, you need to use adapters to smooth out the differences between the different ends and make users happy

You can then simulate a simple implementation of this process

Request an interface using AXIos:

axios({
    url: "xxx".method: "GET",
})
    .then((res) = > {
        console.log("success:", res);
    })
    .catch((err) = > {
        console.log("fail:", err);
    });
Copy the code

Next you need to implement the AXIos function manually:

function axios(config) {
    let adaptor = getDefaultAdaptor();

    // On both the Node and browser sides, it simply goes to a config object and returns a Promise object
    return adaptor(config);
}
Copy the code

Since AXIos can be used on both the browser and node sides, the getDefaultAdaptor function acts as an adaptor, creating different adaptors for different environments

/** * adapter */
function getDefaultAdaptor() {
    let adaptor;

    if (typeofXMLHttpRequest ! = ="undefined") {
        // is the browser environment
        adaptor = xhr;
    } else if (typeofprocess ! = ="undefined") {
        / / the node environment
        adaptor = http;
    }

    return adaptor;
}
Copy the code

XHR and HTTP are two functions that create specific requests. Now that the use of the adapter is complete, let’s see how the interface requests are implemented on different ends

Browser side:

/** * Browser environment */
function xhr(config) {
    return new Promise((resolve, reject) = > {
        const req = new XMLHttpRequest();
        req.open(config.method, config.url, true);

        req.onreadystatechange = function () {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 300) {
                    resolve(req.responseText);
                } else {
                    reject("Request failed"); }}}; req.send(); }); }Copy the code

The node side:

/** * node environment */
function http(config) {
    const url = require("url");
    const http = require("http");
    // Parse the required parameters
    const { hostname, port, path } = url.parse(config.url);
    return new Promise((resolve, reject) = > {
        const options = {
            hostname,
            port,
            path,
            method: config.method,
        };

        const req = http.request(options, function (response) {
            let chunks = [];

            response.on("data".(chunk) = > {
                chunks.push(chunk);
            });

            response.on("end".() = > {
                const res = Buffer.concat(chunks).toString();
                resolve(res);
            });
        });

        // The listening request is abnormal
        req.on("error".(err) = > {
            reject(err);
        });

        // The request is sent
        ren.end();
    });
}
Copy the code