使用promises进行异步编码

时间:2017-09-29 03:10:53

标签: javascript node.js promise

我正在学习节点和承诺。我已经简化了我的问题并在下面分享了我的代码。

我有三个模块:app.js,modLanguage.js和model.js

app.js:

var l = require('../test/modLanguage.js');

var params = [{
   p0: 'johnDoe',
   p1: '12345',
   p2: 0
}];

var lang = l.call(params);
console.log("Needs to run last: " + lang.language);

modLanguage.js:

var call = function(params) {
    var langQuery = require('../test/model.js');
    var userLang = createLanguage();

    userLang.setLanguage('FRENCH');
    console.log("This needs to run first - setting lang French before DB dip: " + userLang.language);

    var myData = langQuery.getLanguage(params)
        // My DB dip
        .then(function(data) {
            var data = JSON.parse(JSON.stringify(data[0]));
            userLang.setLanguage(data[0].Language);
            console.log("Needs to run second - DB dip brought language ENG: " + userLang.language);
            return userLang;
        })
        .catch(function(err) {
            console.log('error');
        });
    return userLang;
}
module.exports.call = call;


function createLanguage() {
    return {
        language: this.language,
        setLanguage: function(language) {
            this.language = language;
            return this.language;
        }
    }
}

model.js是一个简单的模块,它使用params,运行存储过程并通过返回promise来返回数据。

我想阻止在app.js上运行代码,直到从针对Database dip返回的数据初始化对象。但是,按原样,console.log显示:

  

这需要先运行 - 在DB dip之前设置lang French:FRENCH

     

最后需要跑:法语

     

需要跑第二名 - DB dip带来语言ENG:ENG

我想要达到的目的显然是:

  

这需要先运行 - 在DB dip之前设置lang French:FRENCH

     

需要跑第二名 - DB dip带来语言ENG:ENG

     

需要最后运行:ENG

请告知我为实现这一目标需要做出哪些改变?

2 个答案:

答案 0 :(得分:1)

以下是需要更改的行以及原因。

// Instead of assigning this promise to a variable that you never 
// even use, just return the promise to the caller, so caller can wait
// for a result to actually be there.

return langQuery.getLanguage(params)

// Returning userLang will cause your app to process userLang
// before you've attached the proper language to it. Don't return
// it. Instead, return the promise that tells you userLang will
// be ready, as described above.

return userLang; // delete this line


// Now that the promise is returned instead of an incomplete
// object, we can wait for the promise to resolve before logging.

var lang = l.call(params).then(lang => 
  console.log("Needs to run last: " + lang.language)
);

这是一个演示的工作片段。

作为旁注,var基本上不赞成let,它的行为几乎完全相同,除了修复了一些问题!范围界定。

我认为在此示例中,使用constlet更好于let,但代表您使用var,因为它距离小得多使用var

如果您使用的代码库强制您使用var,请确保您研究let / var之间的差异,否则只需使用{{1}退出你的生活会更好。



/** some mock-ups to make the example run in a snippet **/

const module = {exports: {}}

let modelMock = {
    getLanguage(params){
        return Promise.resolve([[{
            Language: 'en-us'
        }]])
    }
}

function require (path) {
    if (path === '../test/model.js')
        return modelMock;
    if (path === '../test/modLanguage.js')
        return module.exports;
}

/********* log to output pre instead of console *********/

console.log = (...args) =>
    [...args].forEach(arg =>
        document.querySelector('pre').innerText += '\n' + arg
  );

/******************* modLanguage.js *********************/

let call = function(params) {
    let langQuery = require('../test/model.js');
    let userLang = createLanguage();

    userLang.setLanguage('FRENCH');
    console.log(
        'This needs to run first - setting lang French before DB dip: '
        + userLang.language
     );

    return langQuery.getLanguage(params)
        // My DB dip
        .then(function(data) {
            // JSON.parse is known to throw. We should always wrap it
            // in a try catch block and decide how to deal with the error.
            // In this case, I'm just rethrowing with clearer message.
            try { data = JSON.parse(JSON.stringify(data[0])); }
            catch(e) { 
                e. message = 
                  'langQuery.getLanguage could not parse provided data';
                throw e;
            }
            
            userLang.setLanguage(data[0].Language);
            
            console.log(
              'Needs to run second - DB dip brought language ENG: '
              + userLang.language
            );
            
            return userLang;
        })
        .catch(function(err) {
            console.error('error');
        });
}


module.exports.call = call;

function createLanguage() {
    return {
        language: this.language,
        setLanguage: function(language) {
            this.language = language;
            return this.language;
        }
    }
}

/************************ app.js ************************/

let l = require('../test/modLanguage.js');

let params = [{
    p0: 'johnDoe',
    p1: '12345',
    p2: 0
}];

l.call(params).then(lang => 
    console.log("Needs to run last: " + lang.language)
);

<pre></pre>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您可以从call返回承诺。不要直接使用返回值设置langl.call(...).then(...);进行最后一次调用并在回调中设置lang