function saveToTheDb(value) { return new Promise(function(resolve, reject) { db.values.insert(value, function(err, user) { // remember error first ;) if (err) { return reject(err); // don't forget to return here } resolve(user); }) } }
这是我从这里看到的代码。我对return关键字感到困惑。
return
对于resolve(user);,我需要return?
resolve(user);
对于reject(user);,我需要return?
reject(user);
无需在new Promise()回调中使用return语句。Promise构造函数不期望回调返回任何类型的返回值。
new Promise()
因此,return在该回调中使用语句的原因仅是为了控制该函数中的执行流程。 如果您希望回调内部的执行完成而又不执行该回调中的任何其他代码,则可以return;在此时发出a 。
return;
例如,您可以这样编写代码,而无需return声明:
function saveToTheDb(value) { return new Promise(function(resolve, reject) { db.values.insert(value, function(err, user) { if (err) { reject(err); } else { resolve(user); } }); } }
在这种情况下,您使用了if / else子句来确保函数中的控制流采用正确的路径,并且return不需要或不使用它。
分发这样的异步函数时,常见的快捷方式是:
function saveToTheDb(value) { return new Promise(function(resolve, reject) { db.values.insert(value, function(err, user) { if (err) return reject(err); resolve(user); }); } }
这在功能上与先前的代码块没有什么不同,但是它的键入更少且更紧凑。return前面的语句reject(err);仅出于控制流的原因,以防止resolve(user);在发生错误的情况下执行该语句,因为所需的控制流将被调用reject(err),然后不在回调中执行其他任何操作。
reject(err);
reject(err)
实际上,return在此特定情况下,实际上甚至不需要最后一个语句中的语句,因为执行诺resolve()后操作reject()将不会做任何事情,因为将诺言锁存到首先解析或拒绝发生的任何事件。但是,通常认为执行不必要的代码是较差的做法,因此许多人会认为最好使用控制结构流,例如if/else或return仅执行所需的代码。
resolve()
reject()
if/else
因此,从技术上讲,这也是可行的,但由于它执行了不必要的代码并且结构也不太清晰,因此不被视为最佳实践:
function saveToTheDb(value) { return new Promise(function(resolve, reject) { db.values.insert(value, function(err, user) { if (err) reject(err); resolve(user); }); } }
仅供参考,您在此处执行的操作称为“ promisifying”,它使常规的异步函数(与回调一起使用)成为返回promise的函数。有一些库和函数可以在一个函数调用中为您“分配”一个函数或函数的整个对象(例如,整个API),因此您不必手动执行此操作。例如,我经常使用Bluebird,它提供Promise.promisify()了一个函数的Promise.promisifyAll()承诺或将一个对象或原型上的所有方法实现了承诺。这非常有用。例如,您可以通过以下方式获得整个fs模块的承诺版本:
Promise.promisify()
Promise.promisifyAll()
fs
var Promise = require('bluebird'); var fs = Promise.promisifyAll(require('fs'));
然后,您可以使用返回承诺的方法,例如:
fs.readFileAsync("file.txt").then(function(data) { // do something with file.txt data here });