Как визуализировать пользовательский интерфейс с несколькими вызовами службы
У меня просто общий вопрос по Javascript. Если мне нужно вызвать две службы для пользовательского интерфейса, и у этих двух вызовов служб есть свои собственные обратные вызовы, но шаблон пользовательского интерфейса должен отображаться только после того, как оба обратных вызова завершат выполнение, какой должен быть наилучший метод Javascript для этого?
invokeServices() {
invokeService1(param1, param2, svcCallback1);
invokeService2(param1, param2, svcCallback2);
//where to render the template???
}
function svcCallback1 (){
//where to render the template???
}
function svcCallback2 (){
//where to render the template???
}
2 ответа
Этот пост может помочь: Марко против Реакта: углубленный взгляд. В частности, ищите раздел на Async
за то, как использовать обещания и <await/>
тег для задержки рендеринга, пока все данные не будут присутствовать.
import fsp from 'fs-promise';
$ var filePath = __dirname + '/hello.txt';
$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});
<await(helloText from readPromise)>
<p>
${helloText}
</p>
</await>
1. Отслеживание завершения обратных вызовов
function invokeServicesAndRender() {
let remaining = 2;
let service1Data;
let service2Data;
invokeService1(param1, param2, (err, data) => {
service1Data = data;
if (!--remaining) done();
});
invokeService2(param1, param2, (err, data) => {
service2Data = data;
if (!--remaining) done();
});
function done() {
// all data is here now, we can render the ui
}
}
2. Обещать и использовать Promise.all
Узел имеет встроенный метод для обещания обратных вызовов: util.promisify
const promisify = require('util').promisify;
const promiseService1 = promisify(invokeService1);
const promiseService2 = promisify(invokeService2);
function invokeServicesAndRender() {
Promise.all([
promiseService1(param1, param2),
promiseService2(param1, param2),
]).then(([service1Data, service2Data]) => {
// all data is here now, we can render the ui
});
}
3. Если вы используете Marko, выполните рендеринг немедленно и передайте обещания в шаблон.
Я вижу, вы отметили этот вопрос marko
, поэтому я упомяну, что с Marko рекомендуется начинать рендеринг немедленно и ждать только тех порций, которые действительно нуждаются в данных. Это позволяет быстрее выводить контент пользователю.
const promisify = require('util').promisify;
const promiseService1 = promisify(invokeService1);
const promiseService2 = promisify(invokeService2);
function invokeServicesAndRender() {
let service1DataPromise = promiseService1(param1, param2);
let service2DataPromise = promiseService2(param1, param2);
template.render({ service1DataPromise, service2DataPromise });
}
В вашем шаблоне вы можете использовать <await>
тег для ожидания данных, где это необходимо:
<h1>Hello World</h1>
<p>this content gets rendered immediately</p>
<await(service1Data from input.service1DataPromise)>
<!-- render content here that needs the service data -->
</await>