如何获取 JavaScript class 方法以等待 return 数据,直到加载构造函数中的数据?
How to get a JavaScript class method to wait to return data until data in the constructor is loaded?
如何让 list()
方法在将其承诺返回给调用者之前等待数据加载到构造函数中?
import fetch from 'node-fetch';
class Employees {
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
(async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
console.log(`work done: got ${this.employees.length} employees`);
})();
}
list() {
return new Promise((resolve) => {
resolve(this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
});
}
}
const employees = new Employees();
(async () => {
console.log(await employees.list());
})();
我建议让构造函数保存数据加载到 this
的承诺,然后 list
可以等待该承诺:
class Employees() {
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
this.initPromise = (async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
console.log(`work done: got ${this.employees.length} employees`);
})();
}
async list() {
await this.initPromise;
return this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
}
}
如果加载尚未完成,则 await
将导致 list
等待,无论需要多长时间。如果加载完成,则 initPromise 处于已解决状态,list
将或多或少立即恢复(当微任务队列执行时)。
使用 Deferred
对象。
a deferred represents work that is not yet finished
// fetch mock with 3 seconds wait
fetch = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
json: () => new Promise((r) => r([
{firstName: 'Arthur', lastName: 'Pym', id: 1},
{firstName: 'August', lastName: 'Barnard', id: 2},
{firstName: 'M.', lastName: 'Poe', id: 3}
]))
});
}, 3000);
});
}
class MyDeferred {
resolve = null;
reject = null;
promise = null;
constructor() {
this.promise = new Promise((res, rej) => {
this.resolve = res;
this.reject = rej;
});
}
}
class Employees {
deferred = new MyDeferred();
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
(async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
this.deferred.resolve();
console.log(`work done: got ${this.employees.length} employees`);
})();
}
list() {
return new Promise((resolve) => {
this.deferred.promise.then(() => {
resolve(this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
});
});
}
}
const employees = new Employees();
(async () => {
console.log(await employees.list());
})();
如何让 list()
方法在将其承诺返回给调用者之前等待数据加载到构造函数中?
import fetch from 'node-fetch';
class Employees {
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
(async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
console.log(`work done: got ${this.employees.length} employees`);
})();
}
list() {
return new Promise((resolve) => {
resolve(this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
});
}
}
const employees = new Employees();
(async () => {
console.log(await employees.list());
})();
我建议让构造函数保存数据加载到 this
的承诺,然后 list
可以等待该承诺:
class Employees() {
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
this.initPromise = (async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
console.log(`work done: got ${this.employees.length} employees`);
})();
}
async list() {
await this.initPromise;
return this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
}
}
如果加载尚未完成,则 await
将导致 list
等待,无论需要多长时间。如果加载完成,则 initPromise 处于已解决状态,list
将或多或少立即恢复(当微任务队列执行时)。
使用 Deferred
对象。
a deferred represents work that is not yet finished
// fetch mock with 3 seconds wait
fetch = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
json: () => new Promise((r) => r([
{firstName: 'Arthur', lastName: 'Pym', id: 1},
{firstName: 'August', lastName: 'Barnard', id: 2},
{firstName: 'M.', lastName: 'Poe', id: 3}
]))
});
}, 3000);
});
}
class MyDeferred {
resolve = null;
reject = null;
promise = null;
constructor() {
this.promise = new Promise((res, rej) => {
this.resolve = res;
this.reject = rej;
});
}
}
class Employees {
deferred = new MyDeferred();
constructor() {
if (Employees._instance) {
return Employees._instance
}
Employees._instance = this;
this.employees = [];
this.dataLoaded = false;
this.url = 'https://raw.githubusercontent.com/graphql-compose/graphql-compose-examples/master/examples/northwind/data/json/employees.json';
(async () => {
const response = await fetch(this.url);
this.employees = await response.json();
this.dataLoaded = true;
this.deferred.resolve();
console.log(`work done: got ${this.employees.length} employees`);
})();
}
list() {
return new Promise((resolve) => {
this.deferred.promise.then(() => {
resolve(this.employees.map(m => `${m.firstName} ${m.lastName} (${m.id})`));
});
});
}
}
const employees = new Employees();
(async () => {
console.log(await employees.list());
})();