2015-07-20 173 views
1

我正试图在NodeJS中使用Bluebird或Q将某些回调转换为Promise,但是我没有成功。 任何人都可以很好,给我一个例子如何将上面的代码转换为承诺?NodeJS中的承诺

在此先感谢

阿德里安

function httpResponse(request, response) { 
    fs.readFile('views/main.ejs', 'utf-8', function readFile(error, file) { 
     if (error) { 
      response.writeHead(200, {"Content-Type": "text/plain"}); 
      response.write('EJS ERROR'); 
      response.end(); 
     } else { 
      // get domains data from db needed for main page 
      dbHandle.queryDB({}, "domains", function dbQueryDB(error, result) { 
       var ejsData = {name: "Cav"}; 
       if (error) { 
        response.write('DB ERROR'); 
        response.end(); 
       } else { 
        ejsData.domains = result; 
        // get machine type data from db needed for main page 
        dbHandle.queryDB({}, "type", function dbQueryDB(error, result) { 
         if (error) { 
          response.write('DB ERROR'); 
          response.end(); 
         } else { 
          ejsData.type = result; 
          //respond index.html 
          response.writeHead(200, {"Content-Type": "text/html"}); 
          response.end(ejs.render(file, ejsData)); 
         } 

        }); 
       } 


      }); 


     } 

    }); 
} 

回答

1

使用bluebird,看看在promisification section

基本上你会做这样的事情:

var fs = require("fs"); 
Promise.promisifyAll(fs); 
Promise.promisifyAll(dbHandle); //do this globally if it is global, not every request! 

那么你的代码将是这样的:

function httpResponse(request, response) { 
     fs.readFileAsync('views/main.ejs', 'utf-8') 
     //Special catch only for EJS errors. ONce past this point in the chain, will not hit again. 

     .then(function(file){ 
      return dbHandle.queryDBAsync({}, "domains"); 
     }) 
     .then(function(domains){ 
      ejsData.domains = domains; 
      return dbHandle.queryDBAsync({}, "type"); 
     }) 
     .then(function(types){ 
      ejsData.type = types; 
      response.writeHead(200, {"Content-Type": "text/html"}); 
      response.end(ejs.render(file, ejsData)); 
     }) 
     .catch(function(error){ 
      response.writeHead(200, {"Content-Type": "text/plain"}); 
      response.write('EJS ERROR'); //or DB errors, add some handling if the error message is important 
      response.end(); 
     }); 
    } 

我这些链接一起保持代码更加平坦。你也可以嵌套承诺。但Promisification是与这里建立图书馆的途径。

编辑 要保持file在范围内,请尝试像这样的Promise设置。请注意嵌套的Promise。

function httpResponse(request, response) { 
     fs.readFileAsync('views/main.ejs', 'utf-8') 
     //Special catch only for EJS errors. ONce past this point in the chain, will not hit again. 


     .then(function(file){ 
      return dbHandle.queryDBAsync({}, "domains") 
      .then(function(domains){ 
       ejsData.domains = domains; 
       return dbHandle.queryDBAsync({}, "type"); 
      }) 
      .then(function(types){ 
       ejsData.type = types; 
       response.writeHead(200, {"Content-Type": "text/html"}); 
       response.end(ejs.render(file, ejsData)); 
      }) 
     .catch(function(error){ 
      response.writeHead(200, {"Content-Type": "text/plain"}); 
      response.write('EJS ERROR'); //or DB errors, add some handling if the error message is important 
      response.end(); 
     }); 
    } 

另一种方法是追踪Promise链外的file变量。当返回readFileAsync时,将result存储为file(您宣布不在该独家新闻中),然后您可以稍后使用它。

+0

感谢您的快速回答。 –

+0

顺便说一下,我在“response.end(ejs.render(file,ejsData));”得到了“文件未定义”。我想这是因为这不是一个闭包,因为它不能看到文件变量。 –

+0

啊,这就是像这样的链接承诺 - '.then()'变量超出范围。我会为你编辑我的答案,以展示如何减少嵌套,但保持范围。 – clay