开始使用Promises

时间:2018-07-24 05:41:41

标签: node.js

我开始使用Promise,但是我对此并不完全理解,您能帮我这个忙吗?我正在验证通过该应用程序发送的所有数据,但仍在加载时不知为何。

这是我的代码(现在我只是在验证POST方法,但是我正在对其进行测试)。

var parse = require('querystring')

/*
    check the regular expression of the final value
    (not special characters accepted)
*/
var dev = function (data) {
    var err = '';
    if (data === undefined || data == null || data.length <= 0) {
        
        err += 1;
    } else {
        if (/[=;(){}/[>'"<]/.test(data)) {
            console.log("special char or invalid data ")
            console.log(data)
            err += 1;
            
        } else {
            

            
        }
    }
    return err < 1 ? data : err
}

/*
    Verify the type of the value or variable
    (recursive functionality)
 */
var verify = function (data) {
    if (Array.isArray(data)) {
        console.log('array ')
        data.forEach(element => {
            // console.log(element)
            verify(element)
            new Promise(function (resolve, reject) {
                verify(element, function (err, element) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(element);
                    }
                });
            })
        });
    } else if (typeof (data) == 'object') {
        //Convert the object on Array to pass this itself to check (recursively)
        console.log('is an object')
        // console.log(data)
        newdata = Object.values(data)
        new Promise(function (resolve, reject) {
            verify(newdata, function (err, newdata) {
                if (err) {
                    reject(err);
                } else {
                    resolve(newdata);
                }
            });
        })
    } else if (typeof (data) == 'function') {
        console.log('is a function')
        // verify(data())
        new Promise(function (resolve, reject) {
            verify(data(), function (err, pipe) {
                if (err) {
                    reject(err);
                } else {
                    resolve(pipe);
                }
            });
        })
    } else {
        // console.log('last level of data')
        return new Promise(function(resolve, reject){
            dev(data, function(err, data){
                if(err){
                    reject(err);
                } else {
                    resolve(data)
                }
            })
        })
        // dev(data)
    }
    // return err < 1 ? data : err;
}




/*
    Check the method of the request and based on this pass the path on req to verify
    (req.body or req.params-req.query)
*/
var controlencoder = function (req, res, next) {
    
    //Print method on console 
    console.log(req.method)
    
    //check the method
    if (req.method == 'PUT' || req.method == 'POST') {
        let body = '';
        let pipe = '';
        req.on('data', chunk => {
            body += chunk.toString();
        });
        req.on('end', () => {
            pipe = parse.parse(body)
            console.log(pipe)
            return new Promise(function (resolve, reject) {
                verify(pipe, function (err) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(pipe);
                    }
                });
            }).then(next())

        });
    } else {
        var pipe = req.params
        return new Promise(function (resolve, reject) {
            verify(pipe, function (err) {
                if (err) {
                    reject(err);
                } else {
                    resolve(pipe);
                }
            });
        }).then(next())
        // console.log(pipe)
    }
    // var pipe = [req.body, req.params]

}

module.exports = controlencoder;

2 个答案:

答案 0 :(得分:1)

In all places where you call verify() and dev() you call it with two arguments, but both functions accept only a single argument. So they will just ignore the functions you pass in.

Now the point of the promises is to get rid of these callbacks so I guess you are halfway through in that process. So let's make all of them return Promises, and only accept a single argument.

Let's review the code:

dev(data)

var dev = function (data) {
    var err = '';
    if (data === undefined || data == null || data.length <= 0) {

        err += 1;
    } else {
        if (/[=;(){}/[>'"<]/.test(data)) {
            console.log("special char or invalid data ")
            console.log(data)
            err += 1;

        } else {

        }
    }
    return err < 1 ? data : err
}
  1. err is initalized to a string, then numbers are added to it in case of problems, and finally it is compared against a number. It happens to work, but you should perhaps use numbers all along, i.e. declare it var err = 0;.
  2. Your regular expression /[=;(){}/[>'"<]/ is badly escaped, you need to put a \ in front of the / in the middle, otherwise it terminates the regular expression. End result: /[=;(){}\/[>'"<]/.
  3. Change the return value to always return a promise: return err < 1 ? Promise.resolve(data) : Promise.reject(err);

verify(data)

var verify = function (data) {
    if (Array.isArray(data)) {
        console.log('array ')
        data.forEach(element => {
            // console.log(element)
            verify(element)
            new Promise(function (resolve, reject) {
                verify(element, function (err, element) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(element);
                    }
                });
            })
        });
  1. Since verify() already returns a promise, we don't need to create any additional Promise objects here. Let's drop the whole new Promise(..){...} thing and just call verify().
  2. We need to verify all elements here and make sure all of them are okay. Using .map() instead of .forEach() we can collect the return values of the verify() calls, which then results in an array of Promise objects. Then we can merge the array of Promise objects using the Promise.all() function. Let's update the code to:

 

var verify = function (data) {
    if (Array.isArray(data)) {
        console.log('array ');
        return Promise.all(
            data.map(element => {
                // console.log(element)
                return verify(element);
            }));
        });

Now all items in the array are mapped to an array of the Promise results of all verify() calls, and Promise.all() merges them together so that if even one verify fails, the returned promise fails.

    } else if (typeof (data) == 'object') {
        //Convert the object on Array to pass this itself to check (recursively)
        console.log('is an object')
        // console.log(data)
        newdata = Object.values(data)
        new Promise(function (resolve, reject) {
            verify(newdata, function (err, newdata) {
                if (err) {
                    reject(err);
                } else {
                    resolve(newdata);
                }
            });
        })
  1. Similar changes here. No need to create new Promise objects when verify already returns a Promise. Let's update to:

    } else if (typeof (data) == 'object') {
        //Convert the object on Array to pass this itself to check (recursively)
        console.log('is an object');
        // console.log(data);
        newdata = Object.values(data);
        return verify(newdata);
    

Identical changes here:

    } else if (typeof (data) == 'function') {
        console.log('is a function')
        // verify(data())
        new Promise(function (resolve, reject) {
            verify(data(), function (err, pipe) {
                if (err) {
                    reject(err);
                } else {
                    resolve(pipe);
                }
            });
        })

is changed to:

    } else if (typeof (data) == 'function') {
        console.log('is a function');
        return verify(data());

And finally:

    } else {
        // console.log('last level of data')
        return new Promise(function(resolve, reject){
            dev(data, function(err, data){
                if(err){
                    reject(err);
                } else {
                    resolve(data)
                }
            })
        })
        // dev(data)
    }
    // return err < 1 ? data : err;
}

is changed to (since dev() also returns a Promise):

    } else {
        // console.log('last level of data')
        return dev(data);
    }
    // return err < 1 ? data : err;
}

controlencoder(req, res, next)

var controlencoder = function (req, res, next) {

    //Print method on console 
    console.log(req.method)

    //check the method
    if (req.method == 'PUT' || req.method == 'POST') {
        let body = '';
        let pipe = '';
        req.on('data', chunk => {
            body += chunk.toString();
        });
        req.on('end', () => {
            pipe = parse.parse(body)
            console.log(pipe)
            return new Promise(function (resolve, reject) {
                verify(pipe, function (err) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(pipe);
                    }
                });
            }).then(next())

        });

Change this to:

var controlencoder = function (req, res, next) {

    //Print method on console 
    console.log(req.method)

    //check the method
    if (req.method == 'PUT' || req.method == 'POST') {
        let body = '';
        let pipe = '';
        req.on('data', chunk => {
            body += chunk.toString();
        });
        req.on('end', () => {
            pipe = parse.parse(body)
            console.log(pipe)
            return verify(pipe).then(next());
        });

And this:

    } else {
        var pipe = req.params
        return new Promise(function (resolve, reject) {
            verify(pipe, function (err) {
                if (err) {
                    reject(err);
                } else {
                    resolve(pipe);
                }
            });
        }).then(next())
        // console.log(pipe)
    }
    // var pipe = [req.body, req.params]
}

.. to this:

    } else {
        var pipe = req.params

        return verify(pipe).then(next());
        // console.log(pipe)
    }
    // var pipe = [req.body, req.params]
}

Hope it works :)

答案 1 :(得分:0)

I just want to share with you the general idea about promises... In your example you are mixing callbacks and promises. Therefore you can't see all the beauty of Promises. In the meantime. Have a look at the following example.

function getCustomer() {
  return Promise((resolve, reject) => {
    // send async request here
    // on response execute resolve(res) or catch error with reject(err)
    // for example
    request
      .get('your_address_here')
      .on('response', (res) => {
        resolve(res)
      })
      .on('error', (err) => {
        reject(err)
      });
  })
}

function getCustomerOrders(customer) {
  return Promise((resolve, reject) => {
    // send async request here
    // on response execute resolve(res) or catch error with reject(err)
    // for example
    request
      .get('your_address_here')
      .on('response', (res) => {
        resolve(res)
      })
      .on('error', (err) => {
        reject(err)
      });
  })
}

// The power of promises comes when you have to execute function consequently or to resolve them all (Promise.all)

getCustomers()
  .then(customer => {
    return getCustomerOrders(customer)
  })
  .then(orders => {
    //customer orders here
    console.log(orders)
  })
  .catch(err => {
    console.log(err)
  })

Or resolve them together if the second promise doesn't rely on the result of the first one

Promise.all([getCustomer(), getCustomerOrders()]).then((values) => {
  console.log(values[0]); //is the result of getCustomer()
  console.log(values[1]); //is the result of getCustomerOrders()
});

Major disadvantage with Promises are

  1. Error handler is only one Somebody might think this is an advantage, but sometimes you need more then one error handler

  2. The lack of conditionality. For example sometimes you need to resolve promises conditionaly. Then the code lost its beauty and readibility