在某些方法异步的情况下,有没有办法在JS中链接方法?

时间:2019-05-08 21:35:13

标签: javascript

我们有一个像这样的验证库。

const cache = [];

function rules(object) {

    return {
        addToCache(value) {
            cache.push(value)
        },
        minLengthStr(property, propertyAlias = property) { 
            const value = object[property];

            const message = 
                typeof value === 'string' && value.length > 2 ? null : `${propertyAlias} is less than 2`;
            cache.push(message);
            return rules(object);
        },

        emptyCollection(property, propertyAlias = property) {
            const value = object[property];

            const message = Array.isArray(value) && value.length <= 0 ?
               `${propertyAlias} collection is empty` : null

            cache.push(message);

            return rules(object);
        },

        isString(property, propertyAlias = property) { 
            debugger;
            const value = object[property];

            const message = typeof value === 'string' ? null : `${propertyAlias} is not a string`;
            cache.push(message);

            return rules(object);
        },

        value() {
            return cache.filter(Boolean);
        }   
    }
}


function validateRunner(value) {
    return rules(value)
}

您可以这样称呼它...

const person = {
        website: 'google.com',
        name: 'Bi',
        age: '23',
        hobbies: [
            'running',
            'hiking'
        ]
    };

 const messages = validateRunner(person)
            .minLengthStr('name', 'eeeeee')
            .isString('name')
            .emptyCollection('hobbies')
            .value()


      console.log(messages) 

Example on CodePen

到目前为止,效果很好。 但是现在我们需要添加一些异步检查。

例如,OKUrl方法。

let cache = [];


function fetchIt(url) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      const message = /http/.test(url) ? `${url} is ok` : null;
      res(message);
    }, 3000)
  })
}


function rules(object) {

  return {
    addToCache(value) {
      cache.push(value)
    },

    async okURL(property, propertyAlias = property) {
      const message = await fetchIt(property);
      return rules(object);
    },

    minLengthStr(property, propertyAlias = property) {
      const value = object[property];

      const message =
        typeof value === 'string' && value.length > 2 ? null : `${propertyAlias} is less than 2`;
      cache.push(message);
      return rules(object);
    },

    emptyCollection(property, propertyAlias = property) {
      const value = object[property];

      const message = Array.isArray(value) && value.length <= 0 ?
        `${propertyAlias} collection is empty` : null

      cache.push(message);

      return rules(object);
    },

    isString(property, propertyAlias = property) {
      debugger;
      const value = object[property];

      const message = typeof value === 'string' ? null : `${propertyAlias} is not a string`;
      cache.push(message);

      return rules(object);
    },

    value() {
      return cache.filter(Boolean);
    }
  }
}


function validateRunner(value) {
  return rules(value)
}


const person = {
  website: 'google.com',
  name: 'Bi',
  age: '23',
  hobbies: [
    'running',
    'hiking'
  ]
};


const messages = validateRunner(person)
  .minLengthStr('name', 'eeeeee')
  .isString('name')
  .emptyCollection('hobbies')
  .okURL('website')
  .value()


console.log(messages)   

WIP Example on Codepen(此示例不起作用-只是一个WIP)

使用一个或两个异步方法是否可能具有像这样的可链接结构?还是要求完全改变其调用方式?

1 个答案:

答案 0 :(得分:0)

let cache = [];

let minLengthStr = function(object, property, propertyAlias = property) {
                 return new Promise(function(resolve, reject) {
                      const value = object[property];
                      const message = typeof value === 'string' && value.length > 2 ? null : `${propertyAlias} is less than 2`;
                      cache.push(message);
                          resolve();
                  });
 };


let emptyCollection = function(object,property, propertyAlias = property) {
                 return new Promise(function(resolve, reject) {
                      const value = object[property];
                      const message = (Array.isArray(value) && value.length <= 0) ? `${propertyAlias} collection is empty` : null;
                      cache.push(message);
                          resolve();
                  });
        };

 let isString = function(object,property, propertyAlias = property) {
                 return new Promise(function(resolve, reject) {
                      const value = object[property];
                      const message = typeof value === 'string' ? null : `${propertyAlias} is not a string`;
                      cache.push(message);
                          resolve();
                  });
        }


  let okURL = function(object,property, propertyAlias = property) {
                 return new Promise(function(resolve, reject) {
                       const value = object[property];
                       const message = /http/.test(value) ? `${value} is ok` : null;
                       cache.push(message);                
                       resolve();
                  });
  }


function validateRunner(value) {
    Promise.all([minLengthStr(value,'name','fakeName'), emptyCollection(value,'hobbies', 'fakeHobbies'), isString(value,'name', 'dummyString'), okURL(value, 'website', 'fakeWebsite')]).then(function() {
      console.log('All completed', cache.filter(Boolean));
    });
}


const person = {
        website: 'google.com',
        name: null,
        age: '23',
        hobbies: []
    };


validateRunner(person);