parse url javascript toàn diện

Nội dung bài viết

Video học lập trình mỗi ngày

parseurl javascript - Là một cụm từ mang ý nghĩa get tất cả params có trên url về thành một object, để sử dụng cho việc lập trình. Dạo gần đây, tôi có làm việc với một API đó là hệ thống paymentwall. Một hệ thống tài chính thế giới. Và rắc rối nảy sinh từ đây. Hãy xem nhé.


Bài viết này ra đời trong lúc tôid di tìm phương án cho một  parseUrl hoàn chỉnh và tôi đã được hơn cả mong đợi trong lúc tìm kiếm. Một bài viết rất hay về cách sử dụng và linh hoạt trong lập trình. Nhìn vào tiêu đề có thể thấy đây là một bào viết khá đơn giản nhưng nội dung của nó rất có ích cho các bạn, và cũng như tôi.


Thoáng qua về parse url javascript

Khi bạn có một string như vậy key=nbadsfsdfsda&uid=xxxx&sign_version=v.1&sign=yyyyyyyy trông nó rất đơn giản mà ai cũng có thể làm được như function sau:

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        obj[key] = value;
        return obj;
    }, {});
}

console.log(parseUrl("key=nbadsfsdfsda&uid=xxxx&sign_version=v.1&sign=yyyyyyyy"))
/*
  {
    key:"nbadsfsdfsda",
    uid:"xxxx",
    sign_version:"v.1",
    sign:"yyyyyyyy"
}
*/

Trên đó, tôi đã sử dụng recude method để giải quyết vấn đề đó một cách dễ dàng đối với bạn và tôi. Nhưng chuyện chưa dừng tại đó khi làm việc với một system lớn như paymentwall thì có rất nhiều trường hợp mà tôi phải gặp phải như dưới đây. Từ từ rồi sẽ hay...

parse url javascript undefined

Giả sử nếu tôi get một api có key=nbadsfsdfsda&uid=xxxx&sign_version=v.1&sign=yyyyyyyy&token như thế này thì sẽ có một vấn đề nhỏ ở đây. Thử nghiệm lại ví dụ trên kia:

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        obj[key] = value;
        return obj;
    }, {});
}

console.log(parseUrl("key=nbadsfsdfsda&uid=xxxx&sign_version=v.1&sign=yyyyyyyy&token"))
/*
  {
    key:"nbadsfsdfsda",
    uid:"xxxx",
    sign_version:"v.1",
    sign:"yyyyyyyy",
    token:undefined
}
*/

Điều không mong muốn đó là token:undefined đã xảy ra. Vì token không có giá trị cho nên nó sẽ nhận undefined chuyện đó là bình thường, và nó không ảnh hưởng điều gì về syntax. Nhưng nếu chúng ta có thể sửa đổi một chút để parseUrl có thể fix điều này. Hãy xem tôi tìm hiểu và làm thế nào?

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');

        //fix undefined
        if (!value) {
            return obj;
        }

        obj[key] = value;
        return obj;
    }, {});
}

console.log(parseUrl("key=nbadsfsdfsda&uid=xxxx&sign_version=v.1&sign=yyyyyyyy&token"))
/*
  {
    key:"nbadsfsdfsda",
    uid:"xxxx",
    sign_version:"v.1",
    sign:"yyyyyyyy"
}
*/

Cách fix đơn giản mà tôi đã thực hiện đó là thêm vào điều kiện:

if (!value) {
     return obj;
}

Rất đơn giản phải không, những điều đó là chuyện nhỏ so với chúng ta, nhưng đây mới là chuyện lớn nè, chúng ta hãy nhìn vào một tình huống khác. Giờ hãy nhìn vào chuỗi này key=yyyy&uid=xxxx&token[pro]=pro&token[basic]=basic Theo cách viết trên, thì nó giống thế này:

{
     key:"yyyy",
     uid:"xxxx",
     token[pro]:"pro",
     token[basic]:"basic"
}

Trong thực tế, rõ ràng nó token thực sự là một loại đối tượng , vì vậy điều này không nên xảy ra, ít nhất là nó như thế này:

{
     key:"yyyy",
     uid:"xxxx",
     token: {pro: "pro", basic:"basic"}
}

Vì vậy, hãy nghiên cứu nó một lần nữa vậy

parse url javascript với Object

Thật ra nó không phức tạp đâu, chẳng qua bạn đọc or do tôi viết vậy thôi. Nguyên tắc cũng không phức tạp. Trên thực tế, nếu một loại object như thế này xuất hiện, chúng ta sẽ coi nó như một object. Sau khi cứ xử lý bình thường như sau, tôi sẽ viết một function deepObj để làm điều đó như sau:

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        if (!value) {
            return obj;
        }
        // obj[key] = value   commetn nó lại
        

        deepObj(obj, key.split(/[\[\]]/g).filter(v => v), value);
        return obj;
    }, {});
}

function deepObj(obj, keys, value) {

    let i = 0;
    for (; i < keys.length - 1; i++) {
        let key = keys[i];

        if (!obj[key]) {  
            obj[key] = {}; 
        }
 
        obj = obj[key];
    }

    obj[keys[i]] = value;
}

console.log(parseUrl("key=yyyy&uid=xxxx&token[pro]=pro&token[basic]=basic"))

/*
  Output:
  {
    key:"yyyy",
    uid:"xxxx",
    token: {
      pro:"pro",
      basic:"basic"
    }
  }
*/

Thật tuyệt vời khi chúng ta có thể tìm những phương pháp như thế này. CHính vì lẽ đó, tôi yêu javascript đến vậy kakaaka. Đến đây thì tôi có thể đưa ra một vài tình huống nữa, nên có thể viết nhanh và không cần phải dài dòng. Nhận một string như sau: key=yyyy&uid=xxxx&token[0]=pro&token[1]=basic thực tế thì chúng ta sẽ nhận được một array như sau:

{
     key:"yyyy",
     uid:"xxxx",
     token: ['pro', 'basic']
}

Không khó gì, chúng ta sẽ quay trở lại deepObj để tiếp tục sử đổi nó một lần nữa, nhưng không ảnh hương đến những chức năng ta đã làm

function deepObj(obj, keys, value) {

    let i = 0;
    for (; i < keys.length - 1; i++) {
        let key = keys[i];

        if (!obj[key]) {  
            //obj[key] = {}; comment chỗ này
            if (keys[i + 1].match(/^\d+$/)) {
                obj[key] = [];
            } else {
                obj[key] = {};
            }
        }
 
        obj = obj[key];
    }

    obj[keys[i]] = value;
}

Rất đơn giản chúng ta chỉ cần comments obj[key] = {}; và thay vào đó:

if (keys[i + 1].match(/^\d+$/)) {
     obj[key] = [];
} else {
     obj[key] = {};
}

Và chạy lại kết quả như sau và đón nhận thành quả:

console.log(parseUrl("key=yyyy&uid=xxxx&token[0]=pro&token[1]=basic"))

/*
  Output:
{
key:"yyyy",
uid:"xxxx",
token:["pro", "basic"]
}
*/

Như vậy một parseUrl hoàn chỉnh sẽ là:

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        if (!value) {
            return obj;
        }
        // obj[key] = value   commetn nó lại
        

        deepObj(obj, key.split(/[\[\]]/g).filter(v => v), value);
        return obj;
    }, {});
}

function deepObj(obj, keys, value) {

    let i = 0;
    for (; i < keys.length - 1; i++) {
        let key = keys[i];

        if (!obj[key]) {  
            //obj[key] = {}; comment chỗ này
            if (keys[i + 1].match(/^\d+$/)) {
                obj[key] = [];
            } else {
                obj[key] = {};
            }
        }
 
        obj = obj[key];
    }

    obj[keys[i]] = value;
}

Có thể bạn đã bị missing