Я пытаюсь вернуть статус входа в систему из функции обратного вызова Cognito, которая написана в NodeJS Lambda. Однако, когда я вызываю API, ответ продолжает загружаться, и я получаю предупреждение об ошибке.
Вот мой код:
'use strict';
global.fetch = require('node-fetch');
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
module.exports.hello = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
message: "Hello there"
}),
};
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
module.exports.register = async (event, context, callback) => {
let poolData = {
UserPoolId : 'xxxxx', // Your user pool id here
ClientId : 'xxxxxxx' // Your client id here
} // the user Pool Data
let userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
let attributeList = [];
let dataEmail = {
Name : 'email',
Value : '[email protected]'
};
let dataName = {
Name : 'name',
Value : 'Jack'
};
var dataPhoneNumber = {
Name : 'phone_number',
Value : '+94234324324234' // your phone number here with +country code and no delimiters in front
};
let attributeEmail = new AmazonCognitoIdentity.CognitoUserAttribute(dataEmail);
let attributeName = new AmazonCognitoIdentity.CognitoUserAttribute(dataName);
var attributePhoneNumber = new AmazonCognitoIdentity.CognitoUserAttribute(dataPhoneNumber);
attributeList.push(attributeEmail);
attributeList.push(attributeName);
attributeList.push(attributePhoneNumber);
userPool.signUp('[email protected]', 'H1%23$4jsk', attributeList, null, function(err, result){
let data = {};
if (err) {
callback(null, {
statusCode: 500,
body: JSON.stringify({
status: 'FAIL',
message: err.message
}),
});
} else {
let cognitoUser = result.user;
callback(null, {
statusCode: 200,
body: JSON.stringify({
status: 'SUCCESS',
message: '',
data: {
username: cognitoUser.getUsername(),
id: result.userSub
}
}),
});
}
})
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
Предупреждающая ошибка выглядит следующим образом:
Serverless: Warning: handler 'register' returned a promise and also uses a callback!
This is problematic and might cause issues in your lambda.
Serverless: Warning: context.done called twice within handler 'register'!
безсерверный.yml
service: test-auth
plugins:
- serverless-offline
provider:
name: aws
runtime: nodejs8.10
stage: dev
region: us-east-1
functions:
hello:
handler: handler.hello
events:
- http:
path: message
method: get
register:
handler: handler.register
events:
- http:
path: register
method: post
Любая помощь будет оценена, спасибо заранее.
РЕДАКТИРОВАТЬ (2019-04-01):
module.exports.register = (event, context) => {
...
userPool.signUp('[email protected]', 'H1%23$4jsk', attributeList, null, function(err, result){
// for testing purpose directly returning
return {
statusCode: 500,
body: JSON.stringify({
status: 'FAIL',
message: err.message
})
}
})
};



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это именно то, что говорится в сообщении об ошибке.
Все функции async возвращают промисы.
module.exports.register = async (event, context, callback) => {}
Вы также используете обратный вызов, вызывая
callback(null, {
statusCode: 500,
body: JSON.stringify({
status: 'FAIL',
message: err.message
}),
});
Вместо использования обратного вызова просто верните либо ошибку, либо действительный ответ.
Я все еще изучаю Node, поэтому извините за нубский вопрос. Разве первый параметр в обратном вызове не должен использоваться для ошибок? В вашем примере первый параметр обратного вызова равен нулю, а затем ошибка.
Вы используете асинхронную функцию с обратным вызовом.
Попробуйте так:
Удалите обратный вызов из асинхронной функции.
async (event, context)
И измените возврат как:
if (err) {
return {
statusCode: 500,
body: JSON.stringify({
status: 'FAIL',
message: err.message
})
}
}
И поставьте await на вызов функции.
Пробовал, все равно получаю предупреждающее сообщение и ничего не возвращает.
Ну ошибка точна. async оборачивает returnpromise. Либо используйте обратный вызов полностью, например:
global.fetch = require('node-fetch');
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
// remove async
module.exports.register = (event, context, callback) => {
...
// if you're using callback, don't use return (setup your callback to be able to handle this value as required) instead do:
// calback({ message: 'Go Serverless v1.0! Your function executed successfully!', event })
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
Или не используйте обратный вызов, используйте async/await (Promise) до конца, например:
module.exports.register = async (event, context) => {
...
// needs promise wrapper, when using with promise, you might want to break up your code to be more modular
const mySignUp = (email, password, attributes, someparam) => {
return new Promise((resolve, reject) => {
userPool.signUp(email, password, attributes, someparam, function(err, result) {
let data = {};
if (err) {
reject({
statusCode: 500,
body: JSON.stringify({
status: 'FAIL',
message: err.message
}),
});
} else {
let cognitoUser = result.user;
resolve({
statusCode: 200,
body: JSON.stringify({
status: 'SUCCESS',
message: '',
data: {
username: cognitoUser.getUsername(),
id: result.userSub
}
}),
});
}
})
});
}
// call the wrapper and return
return await mySignUp('[email protected]', 'H1%23$4jsk', attributeList, null);
// don't use double return
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
Теперь register вернет promise. В другом месте вашего кода вы можете вызвать регистрацию, например:
var result = register();
result
.then(data => console.info(data))
// catches the reject from Promise
.catch(err => console.error(err))
or in async/await function (Note: `await` is valid only inside `async` function)
async function someFunc() {
try {
var result = await register();
// do something with result
console.info(result);
} catch (err) {
// reject from Promise
console.error(err)
}
}
Также обратите внимание, что здесь не требуется use strict, так как модули узлов используют strict по умолчанию.
Спасибо за подробный ответ, однако, когда я только что вернулся, я получаю сообщение об ошибке тайм-аута [Serverless-Offline] Your λ handler 'register' timed out after 30000ms. Я даже пытался увеличить значение тайм-аута в файле YML, но все равно бесполезно (см. мой код EDIT). когда я попробовал обратный вызов, он просто распечатал сообщение в командной строке. Я просто хочу вывести ответ JSON после успешного выполнения функции обратного вызова. Пример обещания, который вы продемонстрировали, работает нормально, однако, поскольку он блокирует, я не хочу его использовать. Любая идея, как я могу решить эту проблему?
await равно blocking, так как выполнение приостанавливается. Если вы не хотите блокировки, используйте обратный вызов then для обещания, например somePromise.then(/*you can pass your callback function here*/() => //do something)
Спасибо за быстрый ответ, после того, как я удалил асинхронность, я не получаю никаких предупреждений. Однако он также ничего не возвращает, если просто вернуть его. Теперь я получаю
[Serverless-Offline] Your λ handler 'register' timed out after 30000ms.Я даже пытался увеличить значение тайм-аута в файле YML, но все равно бесполезно. Любая причина ошибки?