Это мой первый пост на этом сайте, поэтому я заранее извиняюсь за отсутствие данных или тегов и т. Д. Я использую этот сайт в течение многих лет, и он всегда мне помогал, но теперь я действительно потеряни я нигде не смог найти ответ.
У меня есть приложение, в котором мне нужно вызывать веб-службу 10 раз, каждый раз с другим параметром.Возвращаемая полезная нагрузка сложна, поэтому я создал собственный объект для хранения данных.Мне нужны данные из всех 10 вызовов, прежде чем я перейду к своему коду, что привело меня в ад обратного вызоваЯ пытаюсь использовать Обещания, чтобы упростить это, но именно здесь я сталкиваюсь с этой странной проблемой.Я могу повторить эту проблему с помощью простого класса:
Пользовательский объект (Person):
var person = {
firstName : String,
lastName : String,
age : Number
}
function Person() { //getters and setters
} module.exports = Person;
Функция getToken (возвращает определенный токен, необходимый для вызовов веб-службы), здесь замененс простой строкой:
function getToken() {
return new Promise(function(resolve, reject) {
var x = "random token";
console.log('getting token');
setTimeout(function(){resolve(x)}, 200);
});
}
Функция getAction: в моем реальном приложении она вызывает веб-сервис.Здесь он просто создает случайного человека с идентификатором на входе:
function getAction(uuid) {
return new Promise(resolve => {
var newPerson = new Person();
newPerson.setFirstName("John " + uuid);
newPerson.setLastName("Doe");
newPerson.setAge(20);
console.log("---> Returning Person " + newPerson.getFirstName());
setTimeout(function(){resolve(newPerson)}, 300);
});
}
Функция getActions: вызывает getAction для каждого входного параметра.Эта функция сама должна возвращать Обещание, потому что есть другая функция, ожидающая, пока все данные не будут доступны, прежде чем продолжить.
function getActions() {
return new Promise(function(resolve, reject) {
getToken().then(async function(tokenret) {
var userIds = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010" ];
var myPromise = Promise.join;
myPromise(getAction(userIds[0]), getAction(userIds[1]), getAction(userIds[2]), function(personOne, personTwo, personThree) {
console.log("Person One: " + personOne.getFirstName());
console.log("Person Two: " + personTwo.getFirstName());
console.log("Person Three: " + personThree.getFirstName());
});
}).catch(function(rej) {console.log("Promise Failed! " + rej);});
});
}
Вывод для этого выполнения:
---> Returning Person John 001
---> Returning Person John 002
---> Returning Person John 003
Person One: John 003
Person Two: John 003
Person Three: John 003
Мы можем видетьчто функция getAction была выполнена в правильном порядке с правильными параметрами.Но все 3 переменные, созданные в функции getActions, имеют значение из последнего выполнения.
Я также попробовал этот код:
const allPromises = userIds.map(userIds => getAction(userIds));
await Promise.all(allPromises).then(function(allResults) {
console.log("Received " + allResults.length + " records");
var thisPersonZero = allResults[0];
console.log("This person 0: " + thisPersonZero.getFirstName());
var thisPersonOne = allResults[1];
console.log("This person 1 " + + thisPersonOne.getFirstName());
var thisPersonTwo = allResults[2];
console.log("This person 2 " + + thisPersonTwo.getFirstName());
console.log("Recapping");
console.log("This person 0: " + thisPersonZero.getFirstName());
console.log("This person 1: " + thisPersonOne.getFirstName());
console.log("This person 2: " + thisPersonTwo.getFirstName());
});
И я получил такой вывод:
---> Returning Person John 001
---> Returning Person John 002
---> Returning Person John 003
---> Returning Person John 004
---> Returning Person John 005
---> Returning Person John 006
---> Returning Person John 007
---> Returning Person John 008
---> Returning Person John 009
---> Returning Person John 010
Received 10 records
This person 0: John 010
This person 1 John 010
This person 2 John 010
Recapping
This person 0: John 010
This person 1: John 010
This person 2: John 010
Наконец, я попытался использовать await, что привело к еще более странным результатам:
var firstPerson = await getAction(userIds[0]);
console.log("First Person: " + firstPerson.getFirstName());
var secondPerson = await getAction(userIds[1]);
console.log("Second Person: " + secondPerson.getFirstName());
console.log("Recapping");
console.log("First Person: " + firstPerson.getFirstName());
console.log("Second Person: " + secondPerson.getFirstName());
Результат:
---> Returning Person John 001
First Person: John 001
---> Returning Person John 002
Second Person: John 002
Recapping
First Person: John 002
Second Person: John 002
Таким образом, значение верное до обратного вызова для следующего Promise,который заменяет значение для всех переменных.Поведение остается тем же, если я создаю копии переменной, даже используя JSON.parse (JSON.stringify ()).
Этот код отлично работает, если я использую строки вместо объекта Person.Однако было бы крайне обременительно пытаться сделать это без пользовательских объектов.
Я уверен, что делаю какую-то очень простую ошибку, но даже если это кажется очень простым, я ничего не смог найтипо этому конкретному вопросу в любом месте.Эта проблема возникает в Node версий 9.5 и 10, работающих на MacOS (если это имеет какое-либо значение).
Любая помощь будет очень признательна.Заранее спасибо!
Полный фрагмент кода:
// Person.js
var person = {
firstName : String,
lastName : String,
age : Number
}
function Person() {
Person.prototype.setFirstName = function(firstName) { person.firstName = firstName; }
Person.prototype.setLastName = function(lastName) { person.lastName = lastName; }
Person.prototype.setAge = function(age) { person.age = age; }
Person.prototype.getFirstName = function() { return (typeof person.firstName === 'undefined') ? '' : person.firstName; }
Person.prototype.getLastName = function() { return (typeof person.lastName === 'undefined') ? '' : person.lastName; }
Person.prototype.getAge = function() { return (typeof person.age === 'undefined') ? 0 : person.age; }
}
module.exports = Person;
// Error.js
var Promise = require('bluebird');
var Person = require("./models/Person");
function getToken() {
return new Promise(function(resolve, reject) {
var x = "random token";
console.log('getting token');
setTimeout(function(){resolve(x)}, 200);
});
}
function getActions() {
return new Promise(function(resolve, reject) {
getToken().then(async function(tokenret) {
var userIds = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010" ];
/*
var myPromise = Promise.join;
myPromise(getAction(userIds[0]), getAction(userIds[1]), getAction(userIds[2]), function(personOne, personTwo, personThree) {
console.log("Person One: " + personOne.getFirstName());
console.log("Person Two: " + personTwo.getFirstName());
console.log("Person Three: " + personThree.getFirstName());
});
*/
var firstPerson = await getAction(userIds[0]);
console.log("First Person: " + firstPerson.getFirstName());
var secondPerson = await getAction(userIds[1]);
console.log("Second Person: " + secondPerson.getFirstName());
console.log("Recapping");
console.log("First Person: " + firstPerson.getFirstName());
console.log("Second Person: " + secondPerson.getFirstName());
/*
const allPromises = userIds.map(userIds => getAction(userIds));
await Promise.all(allPromises).then(function(allResults) {
for (var x = 0; x < allResults.length; x++)
{
var thisPerson = allResults[x];
console.log("This Person: " + thisPerson.getFirstName());
}
console.log("Received " + allResults.length + " records");
var thisPersonZero = allResults[0];
console.log("This person 0: " + thisPersonZero.getFirstName());
var thisPersonOne = allResults[1];
console.log("This person 1 " + thisPersonOne.getFirstName());
var thisPersonTwo = allResults[2];
console.log("This person 2 " + thisPersonTwo.getFirstName());
console.log("Recapping");
console.log("This person 0: " + thisPersonZero.getFirstName());
console.log("This person 1: " + thisPersonOne.getFirstName());
console.log("This person 2: " + thisPersonTwo.getFirstName());
});
*/
}).catch(function(rej) {console.log("Promise Failed! " + rej);});
});
}
function getAction(uuid) {
return new Promise(resolve => {
var newPerson = new Person();
newPerson.setFirstName("John " + uuid);
newPerson.setLastName("Doe");
newPerson.setAge(20);
console.log("---> Returning Person " + newPerson.getFirstName());
setTimeout(function(){resolve(newPerson)}, 300);
});
}
getActions();