无服务器框架不能使用Promise?

时间:2018-12-06 06:29:02

标签: node.js typescript serverless-framework

我正在尝试使用无服务器框架制作REST api。

某些功能是异步的。

所以我正在使用Promise

但是诺言没有奏效(无回应)

因此,我正在使用await关键字。很好。

我认为这是不好的方法。如何在无服务器框架中使用Promise?

任何建议或建议将不胜感激。预先谢谢你。

4 个答案:

答案 0 :(得分:1)

您可以通过多种方式使用承诺。就个人而言,将诺言分开另一个功能。

我以请求模块为例:

const request = require("request");

// The promise
const requestPromise = (url, options) =>
    new Promise((resolve, reject) => {
        options = options || {};
        const processRequest = (err, response) => (err ? reject(err) : resolve(response));
        request(url, options, processRequest);
    });


// You can use like this
module.exports = (event,context)  => {
    let url = event.url;
    requestPromise(url)
        .then(response => {
            // Do something
            context.succeed({succeed: true /* put return data here */})
        })
        .catch(details => context.fail({error: true, details: details}));
}

// Or this
module.exports = async (event,context)  => {
    try {
        let url = event.url;
        let response = await requestPromise(url);
        // Do something
        context.succeed({succeed: true /* put return data here */});
    } catch (details) {
        context.fail({error: true, details: details});
    }
}

如果您使用异步/等待,则需要在处理程序错误中添加try / catch。

答案 1 :(得分:1)

我现在正在为mysql world数据库编码无服务器无内核api。我昨天不得不解决这个问题。我得出以下解决方案。功能不完整。但是您没有要求。因此,这是一个工作的GET端点,该端点接受各种查询参数以自定义查询。

'use strict';

const pool = require('./database');

module.exports.handler = async (event, context) => new Promise((resolve, reject) => {
    let request = event.extensions.request;
    let response = event.extensions.response;

    try{
        let handleResults = (err, results, fields) => {
            if(err){
                response.status(500).send({
                    success: false,
                    message: err.message,
                });
            }else{
                response.status(200).send({
                    success: true,
                    count: results.length,
                    data: results,
                });
            }
        }

        if(typeof(request.query.id) !== "undefined"){
            // search for a specific region by id
            if (Number.isNaN(Number(request.query.id))) {
                response.status(500).send({
                    success: false,
                    message: "id query param was not a number",
                });
            }

            pool.query("select id,name,code,country_id from regions where id = ?", [request.query.id], handleResults);
        }else if(typeof(request.query.country) !== "undefined"){
            // search for a region list from a specific country
            if (Number.isNaN(Number(request.query.country))) {
                response.status(500).send({
                    success: false,
                    message: "country query param was not a number",
                });
            }

            pool.query("select id,name,code,country_id from regions where country_id = ?", [request.query.country], handleResults);
        }else{
            response.status(400).send({
                success: false,
                message: "Could not find country, or region query parameter. Require a search term"
            });
        }
    }catch(exception){
        response.status(500).send({
            success: false,
            message: exception.message
        });
    }
});

和database.js:

const mysql = require("mysql");
const util = require('util');

const pool = mysql.createPool({
    connectionLimit: 10,

    host: process.env.DATABASE_HOSTNAME,
    user: process.env.DATABASE_USERNAME,
    port: process.env.DATABASE_PORT,
    password: process.env.DATABASE_PASSWORD,
    database: process.env.DATABASE_NAME,
});

pool.getConnection((err, connection) => {
    if (err) {
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            console.error('Database connection was closed.');
        }
        if (err.code === 'ER_CON_COUNT_ERROR') {
            console.error('Database has too many connections.');
        }
        if (err.code === 'ECONNREFUSED') {
            console.error('Database connection was refused.');
        }
    }

    if (connection) connection.release();

    return;
});

// Magic happens here.
pool.query = util.promisify(pool.query);

module.exports = pool;

答案 2 :(得分:1)

我通常在无服务器项目中处理Promises:

//this would me in a module like: services/myhttpservice.js (for example)

//wrap the GET HTTP request in a Promise
module.exports.GetUrlPromise = function(url, cookie_session_value) {
    console.log(new Date().getTime() + " GetUrlPromise() CALLED: " + url);
    var j = request.jar();

    if(cookie_session_value){
         var cookie1 = request.cookie(cookie_name + '=' + cookie_session_value);
         j.setCookie(cookie1, cookie_domain);// domain used by the cookie, maybe make more generic?
    }

    // create the "Basic" auth header
    var auth = "Basic " + Buffer.from(basic_username + ":" + basic_password).toString("base64");

    //create request options
    var options = {
        'method': 'GET',
        'url': url, 
        'jar': j,
        'headers': {
        'Authorization': auth,// set Basic auth header that is the base64 of the un:pw combo
        'Content-Type': 'application/json'
    }
};

return new Promise((resolve, reject) => {
    request(options, function (error, response, body) {
        if(error){
            console.log('error:', error);   
            reject(error);      
        }else{
            console.log('statusCode:', response && response.statusCode); 

            // object for returning response results
            var http_resp = {};
            http_resp._session = GetCookieValue(response);
            http_resp.body = body;
            http_resp.statusCode = response.statusCode;
            //http_resp.response = response;
            http_resp.requestType = 'GET';

            console.log(JSON.stringify(http_resp));
            resolve(http_resp);         
        }
    });
});

}

它使我能够轻松地对服务进行承诺的呼叫:

 //in my controller code:

    myhttpservice.GetUrlPromise(page_url, user_session)
    .then((http_resp)=>{ etc...

答案 3 :(得分:1)

如果使用得当,Await 和 async 是不错的做法。 如果您没有相互依赖的承诺,您可以通过将所有承诺(不带等待)添加到数组中并使用 const responses = await Promise.all(promisesArray) 等待所有响应成功来“并行”调用它们。

有关详细信息,请参阅此答案,该答案很好地解释了Call async/await functions in parallel