Как дождаться ответа на вызов метеора, а затем выполнить другие операторы в javascript?

У меня есть два вызова метеора в клиентских событиях в метеоре, которые я хочу выполнить один за другим. Но когда я отлаживал поток, не следовал тому пути, который я хотел.

client.js

Meteor.call('methodCall',param1,param2,param3,function (error, result) {
    if (error) 
        console.info(error.reason);

    Session.set("xyz",result);
});

var abc=Session.get("xyz");

Meteor.call('methodCall',abc,param2,param3,function (error, result) {
    if (error) 
        console.info(error.reason);

    console.info("result: "+result);
    Session.set("cdf",result);
}); 

var pqr=Session.get("cdf");

Как видите, это код, который я хочу запускать в последовательном порядке, то есть один за другим. Но когда я отладил код, я обнаружил, что порядок выполнения:

1. Meteor will be called
3. session.get("xyz") return undefined.
4. Meteor will be called
6. session.get("cdf") return undefined.
2. session.set() will have results as value.
5. session.get() will not have any value.

Второй meteor.call () не будет выполняться успешно, потому что 1-й параметр не будет иметь никакого значения, поскольку шаг 3 выполнялся до шага 2. Итак, есть ли способ добиться этого и дождаться завершения вызова метеора для выполнения следующих инструкций?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 191
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Один из способов - немного реорганизовать ваш код.

Meteor.call('methodCall',param1,param2,param3,function (error, result) 
{
  if (error) console.info(error.reason);
  Session.set("xyz",result);
  var abc=Session.get("xyz");
  Meteor.call('methodCall',abc,param2,param3,function (error, result) 
  {
    if (error) console.info(error.reason);
    console.info("result: "+result);
    Session.set("cdf",result);
    var pqr=Session.get("cdf");
  });
});
Ответ принят как подходящий

Я провел некоторое исследование различных вариантов такой ситуации, поскольку некоторые другие здесь тоже могли столкнуться с ней.

Вариант А - вложенные вызовы в клиенте

Первый и наиболее очевидный - выполнять вложенные вызовы. Это означает вызов следующей функции после получения результата в обратном вызове.

// level 1
Meteor.call('methodCall', param1, param2, param3, function (error, result) {
    // level 2
    if (error) console.info(error.reason);

    Session.set("xyz",result);

    Meteor.call('methodCall',result, param2, param3, function (error, result) {
        // level 3...
        if (error) console.info(error.reason);

        console.info("result: "+result);
        Session.set("cdf",result);
    }); 

});

Плюсы: классический способ js, не требуются новые причудливые концепции, серверные методы придерживаются простой логики, в то время как клиент умирает от сложной работы

Минусы: некрасивый, может вызвать путаницу и иногда трудно отладить

Требует:Template.autorun или Tracker.autorun, чтобы реагировать на изменения из Session.


Вариант B - обернуть асинхронно

Многие, возможно, уже сочли этот метод лучшим выбором для структурирования асинхронного кода в код синхронизации.

Волокна (и wrapAsync, использующие волокна) делают код только смотрю для синхронизации, но характер выполнения остается асинхронным. Это работает так же, как работают обещания или как работает async / await.

Плюсы: мощный, когда в одной среде

Минусы: нельзя использовать с Meteor.call

Требует: волокно для запуска

Проблема с Meteor.call

Однако вы не можете легко вызвать метод Meteor, используя эту функцию. Рассмотрим следующий код

const param1 = "param1";
const param2 = "param2";
const param3 = "param3";


const asyncCall = Meteor.wrapAsync(Meteor.call);
const result1 = asyncCall("methodCall", param1, param2, param3);
// result1 will be undefined

Для дальнейшего пояснения я процитирую документация:

On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn’t have fibers, so there is not actually any way it can block on the remote execution of a method.

Резюме: Meteor.wrapAsync нельзя использовать вместе с Meteor.call.


Вариант C - Объединение одним методом

Вместо того, чтобы пытаться создать синхронизированную последовательность метеорных вызовов, вы также можете предоставить все параметры и логику одному серверному методу, который возвращает объект, который хранит все возвращаемые значения:

client.js

const param1 = "param1";
const param2 = "param2";
const param3 = "param3";


Meteor.call('methodCall', param1, param2, param3, function (err, result) {
  const xyz = result.xyz;
  const cdf = result.cdf;
});

server.js

function _methodCall(p1, p2, p3) {
  // ... 
  return result;
}

Meteor.methods({
  'methodCall'(p1, p2, p3) {
    const result1 = _methodCall(p1, p2, p3);
    const result2 = _methodCall(result1, p2, p3);
    return {
      xyz: result1,
      cdf: result2,
    }
  }
})

Это создаст последовательное выполнение (следуя последовательной логике, которую вы указали в своем вопросе) и вернет все его результаты в связанном объекте.

Плюсы: последовательно по желанию, один запрос - все результаты Минусы: один дополнительный метод, который нужно протестировать, может привести к тесному взаимодействию между методами, возвращаемые объекты могут стать большими и сложными для синтаксического анализа для клинета. Требуется: хорошее чутье при разработке метода.

Если я найду другие варианты, я добавлю их в этот пост.

Вы должны использовать обещание, например, будущие волокна

на сервере

Meteor.methods({
'methodCall': function(params...){
  var future = new Future();
  try{
    your code...
    future.return(result)
  catch(e){
    future.throw(e)
  }finally{
    return future.wait();
  }
 },
})

На клиенте

Meteor.call('methodCall',params...,(err,res)=>{
  if (err){
   console.info(err);
  }else{
   console.info(res);
  }
});

ссылка на ref https://github.com/jagi/meteor-astronomy/issues/562

Другие вопросы по теме