2016-11-28 89 views
2

我正在编写一些加密两个用户之间的通信通道的代码。 的步骤如下Promise.method()函数不按我期望的方式工作

  • 检查中mongoDb
  • 存在该频道的密码如果是,取cipher和加密输入数据
  • 如果没有,创建一个新的密码,将其保存到mongoDb和加密输入数据

代码使用crypto模块,其在芯中的几个同步库之一的NodeJS

创建加密,并将其返回作为一个承诺使用Promise.method()

cipher.encryptTextAsPromise = Promise.method((cipher, plainText) => { 
    if (!(typeof plainText === 'string')) { 
    throw new Error("2nd param must be plain text"); 
    let cipherText = ''; 
    cipher.on('readable',() => { 
     var data = cipher.read(); 
     if (data) 
     cipherText += data.toString('hex'); 
    }); 
    cipher.on('end',() => { 
     return cipherText; 
    }); 
    cipher.write(plainText); 
    cipher.end(); 
    } 
}); 

加密数据通过回调函数

cipher.createCipher = Promise.method((pw) => { 
    if (!pw) { 
    throw new Error('Passphrase must be provided'); 
    } 
    return crypto.createCipher('aes192', pw); 
}); 

加密数据。

cipher.encryptText = (cipher, plainText, callback) => { 
    if (!(typeof plainText === 'string')) { 
    throw new Error("2nd param must be plain text"); 
    } 
    try { 
    let cipherText = ''; 
    cipher.on('readable',() => { 
     var data = cipher.read(); 
     if (data) 
     cipherText += data.toString('hex'); 
    }); 
    cipher.on('end',() => { 
     callback(null, cipherText); 
    }); 
    cipher.write(plainText); 
    cipher.end(); 
    } catch (e) { 
    callback(e, null); 
    } 
} 

我无法将这两个链接在一起。我已经是一个可怕的反模式比陷入回调地狱

cipher.createCipher('secretWord') 
    .then((data) => { 
    cipher.encryptTextasPromise(data, 'hello world') 
    .then((data) => { 
     console.log(data); 
    }) 
    .catch((err) => { 
     console.log(err); 
    }) 
    }) 
    .catch((err) => { 
    console.log(err); 
    }) 

mongoDbSearch(username) 
    .then((data) => { 
    if (data) { 
     // Cipher exists, retrieve and encrypt 
    }else { 
     // Create new cipher and save 
     someMongoSave() 
     .then((data) => { 
      // Cipher exists now, retrieve and encrypt 
     }) 
    } 
    }) 
    .catch((mongoErr) => { 
    console.log(mongoErr); 
    }) 

的代码是一个有点不完整,因为我仍然在试图掌握这个概念变得更糟。此外,我试图链接createCipherencryptTextAsPromise正在返回undefined的数据。我曾试着将这些作为普通回调书写,然后使用Promise.promisfyAll(),这只是另一种反模式。

+1

好吧,'cipher.encryptTextAsPromise'永远不会返回一个值,所以可以解析为'undefined' - 即使您修复了逻辑 –

+1

并且在抛出一个错误后,后续行不会被执行! – undefined

+0

这不是一个答案,但我相当肯定你不正确地使用'Promise.method'。从[文档](http://bluebirdjs.com/docs/api/promise.method.html),很明显,它意味着从一个**同步**方法,可能会返回其结果或抛出一个错误。你的功能不同步。而且,既然你是写他们的人,就没有必要包装它们。只需在其中使用'Promise':http://pastie.org/10971651(另请注意,Pastie修复了@undefined上面提到的问题。) –

回答

3

Promise.method似乎对createCipher有意义,但可能不适用于encryptTextAsPromise

这里有一个版本,应该指出你正确的方向,蒸馏各种T.J. Crowder's,Jaromanda X's和undefined对这个问题的评论;看到代码的注释更多:

// For this one, `Promise.method` still makes sense (although doing it with 
// your own promise is also perfectly reasonable) 
cipher.createCipher = Promise.method(pw => { 
    if (!pw) { 
    throw new Error('Passphrase must be provided'); 
    } 
    return crypto.createCipher('aes192', pw); 
}); 

// For this one, your own promise makes sense 
cipher.encryptTextAsPromise = (cipher, plainText) => { 
    return new Promise(resolve => { 
    if (!(typeof plainText === 'string')) { 
     // It's fine to throw here (it will get converted into a rejection), 
     // or add `reject` to the arguments list above and call 
     // that and return instead: 
     // reject(new Error("2nd param must be plain text")); 
     // return; 
     throw new Error("2nd param must be plain text"); 
    } 
    let cipherText = ''; 
    cipher.on('readable',() => { 
     var data = cipher.read(); 
     if (data) 
     cipherText += data.toString('hex'); 
    }); 
    cipher.on('end',() => { 
     resolve(cipherText); 
    }); 
    cipher.write(plainText); 
    cipher.end(); 
    }); 
}; 

// Usage: 
cipher.createCipher('secretWord') 
.then(data => cipher.encryptTextAsPromise(data, 'hello world')) 
.then(data => console.log(data)) // See 1 below 
.catch(err => console.log(err)); 

mongoDbSearch(username) 
.then(data => data || someMongoSave(data)) // You pass `data` to `someMongoSave`, presumably? 
.then(data => { 
    // Cipher exists, retrieve and encrypt 
}) 
.catch(mongoErr => { 
    console.log(mongoErr); 
}); 

另外,重新

if (!(typeof plainText === 'string')) { 

有一个JavaScript !==运营商。 Jus'说'。 ; -D

+0

,是否有任何理由说明你没有添加'reject'并删除'try catch'块。由于密码不是有效的类型,加密也会引发错误。 –

+0

@VarunAgarwal:没有理由,事实上我会注意到这一点。要么绝对好。抛出'Promise'构造函数回调会被转换为拒绝,所以有人喜欢这样做,因为它更像是同步代码。 –

+0

'你把数据传给了一些MongoSave,据推测?'在那个时候数据将被保证是错误的,所以,我不这么认为 –