我正在尝试使用异步身份验证处理程序,该处理程序可以具有回调或承诺的实现。范围是包装此函数以便始终返回promise,因此我可以使用它进一步回调/保证不可知。
如果有人可以为这些场景提供一些帮助,我将非常感激,其中一个例子就是现实生活。
如果功能如下:
function getData(id, callback) {
var deferred = Q.defer();
apiCall('/path/to/id', function (err, data) {
if (err) deferred.reject(new Error(err));
//do something with data
deferred.resolve(processedData);
}
deferred.promise.nodeify(callback);
return deferred.promise;
}
我希望以这种方式使用.fromCallback
function myProcessedDataFunction(id) {
return Promise.fromCallback(function (callback) {
return getData(id, callback);
}, {multiArgs: true});
}
这会有用吗? myProcessedDataFunction会返回正确的承诺吗?
现实世界的例子是:
我有一个身份验证处理程序,可能会或可能不会使用回调函数实现,同时可以使用promises实现;或者它可能返回真/假值;
function authHandlerImplementation1(username, password) {
return (username === 'validUsername' && password === 'validPassword');
}
function authHandlerImplementation2(username, password, callback) {
apiCall('/path/to/authorization', function (err, result) {
if (err) return callback(err, null);
callback(null, result);
});
}
function authHandlerImplementation3(username, password) {
return new Promise(function (reject, resolve) {
apiCall('/path/to/authorization', function (err, result) {
if (err) return reject(err);
resove(result);
});
});
}
function authHandlerImplementation4(username, password, callback) {
var deferred = Q.defer();
apiCall('/path/to/id', function (err, data) {
if (err) deferred.reject(new Error(err));
//do something with data
deferred.resolve(processedData);
}
deferred.promise.nodeify(callback);
return deferred.promise;
}
我将尝试第5个蓝鸟实施。
function authHandlerImplementation5(username, password, callback) {
return apiCall('/path/to/id', callback).asCallback(callback); // I hope this is the right way to do it (correct me if I'm wrong, please)
}
我的checkAuth函数使用authHandler实现,并希望与回调/承诺无关。
function checkAuth(username, password) {
var self = this;
return Promise.fromCallback(function(callback) {
return self.authHandler(username, password, callback);
}, {multiArgs: true});
}
如果authHandlerImplementation不使用回调(只返回一个值)(implementation1),checkAuth挂起,没有任何反应,我的测试失败。
是否有任何Bluebird方法可以将任何类型的authHandler实现包装到promise中(简单的返回,回调或promise实现)?
答案 0 :(得分:2)
不,Bluebird没有这样的实用程序。如果你将它们作为API提供,那么支持回调和promises是很好的,但是当你需要使用API时却不是这样 - 区分方法是否需要回调或返回promises或者两者都不可能来自外部,并编写代码来动态地计算它(每次通话)都可能,但很尴尬。
Bluebird 有一个实用程序包含可能返回,抛出或返回一个promise的函数,它被称为Promise.method
(并且还有Promise.try
立即调用它)。
如果他们想要传递一个异步的auth-handler,我建议强制你的调用者使用promises。如果他们只有一个基于回调的版本,他们仍然可以将它自己包装在Promise.promisify
中,然后再提供给你。
答案 1 :(得分:0)
我尝试了一些东西,并且设法让它发挥作用。我将在下面提供我尝试过的方法的详细信息。该方案适用于json-rpc 2.0服务器实现,该实现接收authHandler函数实现,以检查请求中提供的凭据的有效性。
更新:
在authHandler上使用Promise.method
var promisifiedAuthHandler = Promise.method(self.authHandler);
适用于authHandler的同步实现。
回调实现失败。
在Promise.method中包含的authHandler上使用Promise.promisify适用于回调实现
var promisifiedAuthHandler = Promise.promisify(Promise.method(self.authHandler));
。
无法进行同步实施。
为authHandler提供回调(即使它在实现中不使用它)适用于所有方法。它是这样的(写一般情况,这是使用ES5-Class node module编写的模块的一部分):
function _checkAuth(req) {
var self = this;
var credentials = self._getCredentials(req);
var promisifiedAuthHandler = Promise.method(self.authHandler); // for the sync implementation
switch (authType) {
// general case, let's say, there are several types
// will just write one as an example.
case Authorization.WHATEVERTYPE:
return promisifiedAuthHandler(credentials, function callback(err, result) {
if (err) return Promise.reject(err);
return Promise.resolve(result);
}
}
}
和server.enableCookie / JWT / BasicAuth处理程序可以用上面提到的三种方式实现:sync / callback / promise;如下:
server.enableCookieAuth(function (cookie) {
return (cookie === validCookieValue);
});
server.enableCookieAuth(function (cookie, callback) {
apiCall('path/to/auth', function(err, result) {
// apiCall could have a promise implementation, as well, and could
// be used with .then/.catch, but this is not that important here, since we care
// about the handler implementation)
if (err) return callback(err, null);
callback(null, result); // can be returned
}
});
server.enableCookieAuth(function (cookie) {
// let's write the apiCall with promise handling, since we mentioned it above
return apiCall('path/to/auth').then(function (result) {
return Promise.resolve(result);
}).catch(function (err) {
return Promise.reject(err);
});
});
现在,我们可以在内部使用我们的_checkAuth函数,只使用promises,与authHandler函数实现无关。如:
handleHttp: function(req, res) {
var self = this;
// ...other processing
self._checkAuth(req).then(function (result) {
// check if the user is authed or not
if (result) {
// further process the request
} else {
// handle unauthorized request
}
}).catch(function (err) {
// handle internal server or api call (or whatever) error
});
}
诀窍是用promise实现编写回调函数。我们总是为authHandler提供一个回调实现,即使authHandler没有使用它。这样,如果auth处理程序实现使用回调样式实现,我们总是确保它返回一个promise。
欢迎所有评论,我想听听有关此事的一些意见!
感谢您的及时回复!