Jak zawijać wywołania funkcji asynchronicznej w funkcję synchronizacji w Node.js lub Javascript?

122

Załóżmy, że utrzymujesz bibliotekę, która ujawnia funkcję getData. Użytkownicy nazwać uzyskać rzeczywiste dane:
var output = getData();
Pod kaptur dane są zapisywane w pliku, dzięki czemu realizowane getDataprzy użyciu node.js wbudowanej fs.readFileSync. To oczywiste, że zarówno getDatai fs.readFileSyncsą funkcjami synchronizacji. Pewnego dnia powiedziano Ci, aby przełączyć bazowe źródło danych do repozytorium, takiego jak MongoDB, do którego można uzyskać dostęp tylko asynchronicznie. Powiedziano ci również, abyś nie wkurzał swoich użytkowników, getDataAPI nie może zostać zmienione tak, aby zwracało jedynie obietnicę lub wymagało parametru wywołania zwrotnego. Jak spełniasz oba wymagania?

Funkcja asynchroniczna wykorzystująca wywołanie zwrotne / obietnicę to DNA języków JavasSript i Node.js. Każda nietrywialna aplikacja JS jest prawdopodobnie przesiąknięta tym stylem kodowania. Ale ta praktyka może łatwo doprowadzić do tak zwanej piramidy zagłady. Co gorsza, jeśli jakikolwiek kod w jakimkolwiek obiekcie wywołującym w łańcuchu wywołań zależy od wyniku funkcji asynchronicznej, ten kod również musi zostać opakowany w funkcję wywołania zwrotnego, nakładając na wywołującego ograniczenie stylu kodowania. Od czasu do czasu potrzebuję hermetyzowania funkcji asynchronicznej (często dostarczanej w bibliotece innej firmy) w funkcję synchronizacji, aby uniknąć masowego globalnego ponownego fakturowania. Poszukiwanie rozwiązania na ten temat zwykle kończyło się na Node Fiberslub pakiety npm pochodzące z niego. Ale włókna po prostu nie mogą rozwiązać problemu, z którym mam do czynienia. Nawet przykład podany przez autora Fibersa ilustruje brak:

...
Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

Rzeczywista wydajność:

wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)

Jeśli funkcja Fiber naprawdę zmienia uśpienie funkcji asynchronicznej w synchronizację, wynik powinien wyglądać następująco:

wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main

Stworzyłem kolejny prosty przykład w JSFiddle i szukam kodu, który zapewni oczekiwane wyniki. Przyjmuję rozwiązanie, które działa tylko w Node.js, więc możesz wymagać dowolnego pakietu npm, mimo że nie działa w JSFiddle.

skr
źródło
2
Funkcje asynchroniczne nigdy nie mogą być synchronizowane w Node, a nawet gdyby tak było, nie należy tego robić. Problem polega na tym, że w module fs widać zupełnie osobne funkcje synchronicznego i asynchronicznego dostępu do systemu plików. Najlepsze, co możesz zrobić, to zamaskować wygląd asynchronii za pomocą obietnic lub programów (generatory w ES6). Aby zarządzać piramidami wywołań zwrotnych, nadaj im nazwy zamiast definiowania w wywołaniu funkcji i użyj czegoś takiego jak biblioteka asynchroniczna.
qubyte
8
Dla dandavisa asynchronizacja przesyła szczegóły implementacji do łańcucha wywołań, czasami wymuszając globalną refaktoryzację. Jest to szkodliwe, a nawet katastrofalne w przypadku złożonych aplikacji, w których ważna jest modularyzacja i izolacja.
skrót
4
„Piramida zagłady” to tylko przedstawienie problemu. Obietnica może ją ukryć lub ukryć, ale nie może sprostać prawdziwemu wyzwaniu: Jeśli wywołujący funkcję asynchroniczną zależy od wyników funkcji asynchronicznej, musi użyć wywołania zwrotnego, tak samo jak jej wywołujący itd. Jest to klasyczny przykład narzucania ograniczeń na dzwoniącego po prostu ze względu na szczegóły implementacji.
skrót
1
@abbr: Dzięki za moduł deasync, opis twojego problemu jest dokładnie tym, czego szukałem i nie mogłem znaleźć żadnych wykonalnych rozwiązań. Bawiłem się generatorami i iteracjami, ale doszedłem do tych samych wniosków, co ty.
Kevin Jhangiani,
2
Warto zauważyć, że wymuszanie synchronizacji funkcji asynchronicznej prawie nigdy nie jest dobrym pomysłem . Jesteś prawie zawsze mają lepsze rozwiązanie, które utrzymuje asynchronicznej-ności funkcji nienaruszonym, a jednocześnie osiągnąć ten sam efekt (jak sekwencjonowanie, zmiennym otoczeniu, etc).
Madara's Ghost

Odpowiedzi:

105

deasync zamienia funkcję asynchroniczną w synchronizację, zaimplementowaną z mechanizmem blokującym, wywołując pętlę zdarzeń Node.js w warstwie JavaScript. W rezultacie deasync blokuje tylko kolejny kod przed uruchomieniem, bez blokowania całego wątku ani konieczności oczekiwania na zajętość. W tym module jest odpowiedź na wyzwanie jsFiddle:

function AnticipatedSyncFunction(){
  var ret;
  setTimeout(function(){
      ret = "hello";
  },3000);
  while(ret === undefined) {
    require('deasync').runLoopOnce();
  }
  return ret;    
}


var output = AnticipatedSyncFunction();
//expected: output=hello (after waiting for 3 sec)
console.log("output="+output);
//actual: output=hello (after waiting for 3 sec)

(zastrzeżenie: jestem współautorem deasync. Moduł został utworzony po wysłaniu tego pytania i nie znalazł żadnej działającej propozycji.)

skr
źródło
Czy ktoś inny miał z tym szczęście? Nie mogę sprawić, żeby to zadziałało.
newman
3
Nie mogę sprawić, żeby to działało poprawnie. powinieneś ulepszyć swoją dokumentację dla tego modułu, jeśli chcesz, aby był bardziej używany. Wątpię, czy autorzy dokładnie wiedzą, jakie są konsekwencje korzystania z modułu, a jeśli tak, to na pewno ich nie dokumentują.
Alexander Mills
5
Jak dotąd istnieje jeden potwierdzony problem udokumentowany w narzędziu do śledzenia problemów na githubie. Problem został rozwiązany w Node v0.12. Reszta, o której wiem, to tylko bezpodstawne spekulacje, których nie warto dokumentować. Jeśli uważasz, że twój problem jest spowodowany przez deasync, opublikuj samodzielny scenariusz, który można powielić, a ja się nim zajmę.
skrót
Próbowałem go użyć i dostałem kilka ulepszeń w moim skrypcie, ale nadal nie miałem szczęścia z datą. Zmodyfikowałem kod w następujący sposób: function AnticipatedSyncFunction(){ var ret; setTimeout(function(){ var startdate = new Date() //console.log(startdate) ret = "hello" + startdate; },3000); while(ret === undefined) { require('deasync').runLoopOnce(); } return ret; } var output = AnticipatedSyncFunction(); var startdate = new Date() console.log(startdate) console.log("output="+output); i spodziewam się, że dane wyjściowe będą miały 3 sekundy różnej daty!
Alex
@abbr można to przeglądać i używać bez zależności od węzła>
Gandhi
5

Istnieje również moduł synchronizacji npm. który służy do synchronizacji procesu wykonywania zapytania.

Jeśli chcesz uruchamiać zapytania równoległe w sposób synchroniczny, ogranicz węzeł, aby to zrobić, ponieważ nigdy nie czeka na odpowiedź. i moduł synchronizacji jest doskonały do ​​tego rodzaju rozwiązań.

Przykładowy kod

/*require sync module*/
var Sync = require('sync');
    app.get('/',function(req,res,next){
      story.find().exec(function(err,data){
        var sync_function_data = find_user.sync(null, {name: "sanjeev"});
          res.send({story:data,user:sync_function_data});
        });
    });


    /*****sync function defined here *******/
    function find_user(req_json, callback) {
        process.nextTick(function () {

            users.find(req_json,function (err,data)
            {
                if (!err) {
                    callback(null, data);
                } else {
                    callback(null, err);
                }
            });
        });
    }

odnośnik referencyjny: https://www.npmjs.com/package/sync

sanjeev kumar
źródło
4

Jeśli funkcja Fiber naprawdę zmienia uśpienie funkcji asynchronicznej w synchronizację

Tak. Wewnątrz włókna funkcja czeka przed zalogowaniem ok. Włókna nie sprawiają, że funkcje asynchroniczne są synchroniczne, ale pozwalają na pisanie kodu wyglądającego synchronicznie, który używa funkcji asynchronicznych, a następnie będzie działać asynchronicznie wewnątrz pliku Fiber.

Od czasu do czasu odkrywam potrzebę hermetyzowania funkcji asynchronicznej w funkcję synchronizacji, aby uniknąć masowego globalnego ponownego fakturowania.

Nie możesz. Niemożliwe jest synchronizowanie kodu asynchronicznego. Będziesz musiał przewidzieć to w swoim kodzie globalnym i od początku napisać go w stylu asynchronicznym. To, czy zawiniesz globalny kod we włókno, użyjesz obietnic, generatorów obietnic czy prostych wywołań zwrotnych, zależy od twoich preferencji.

Moim celem jest zminimalizowanie wpływu na dzwoniącego, gdy metoda pozyskiwania danych zostanie zmieniona z synchronizacji na asynchroniczną

Mogą to zrobić zarówno obietnice, jak i włókna.

Bergi
źródło
1
to jest ABSOLUTNIE najgorsza rzecz, jaką można osiągnąć dzięki Node.js: „synchronicznie wyglądający kod, który używa funkcji asynchronicznych, a następnie będzie działał asynchronicznie”. jeśli twoje API to zrobi, zrujnujesz życie. jeśli jest asynchroniczna, powinna wymagać wywołania zwrotnego i zgłosić błąd, jeśli nie zostanie podana funkcja zwrotna. to najlepszy sposób na stworzenie API, chyba że Twoim celem jest oszukanie ludzi.
Alexander Mills
@AlexMills: Tak, to byłoby naprawdę okropne . Jednak na szczęście nie jest to możliwe przez API. Asynchroniczne API zawsze musi akceptować wywołanie zwrotne / zwracać obietnicę / oczekiwać, że zostanie uruchomione wewnątrz włókna - bez niego nie działa. Afaik, włókna były najczęściej używane w skryptach quick'n'dirty, które blokowały i nie mają żadnej współbieżności, ale chcą używać asynchronicznych interfejsów API; tak jak w węźle, czasami zdarzają się przypadki, w których użyjesz fsmetod synchronicznych .
Bergi
2
Generalnie lubię node. Zwłaszcza jeśli mogę użyć maszynopisu zamiast czystego js. Ale ten cały nonsens asynchroniczny, który przenika wszystko, co robisz i dosłownie infekuje każdą funkcję w łańcuchu wywołań, gdy tylko zdecydujesz się wykonać pojedyncze wywołanie asynchroniczne, jest czymś, czego naprawdę ... naprawdę nienawidzę. Async api jest jak choroba zakaźna, jedno wywołanie infekuje całą bazę kodu, zmuszając Cię do przepisania całego posiadanego kodu. Naprawdę nie rozumiem, jak ktokolwiek może twierdzić, że to dobra rzecz.
Kris
@Kris Node używa modelu asynchronicznego dla zadań IO, ponieważ jest szybki i prosty. Możesz także robić wiele rzeczy synchronicznie, ale blokowanie jest powolne, ponieważ nie możesz nic robić jednocześnie - chyba że wybierzesz wątki, co komplikuje wszystko.
Bergi
@Bergi Przeczytałem manifest, więc znam argumenty. Ale zmiana istniejącego kodu na asynchroniczny w momencie trafienia pierwszego wywołania interfejsu API, które nie ma odpowiednika synchronizacji, nie jest prosta. Wszystko się psuje i każdy wiersz kodu musi zostać przeanalizowany. O ile twój kod nie jest trywialny, gwarantuję ... zajmie trochę czasu, aby przekonwertować go i ponownie uruchomić po przekonwertowaniu całości na idiom asynchroniczny.
Kris
2

Musisz korzystać z obietnic:

const asyncOperation = () => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{resolve("hi")}, 3000)
    })
}

const asyncFunction = async () => {
    return await asyncOperation();
}

const topDog = () => {
    asyncFunction().then((res) => {
        console.log(res);
    });
}

Bardziej lubię definicje funkcji strzałek. Ale dowolny ciąg w postaci „() => {...}” można również zapisać jako „funkcja () {...}”

Zatem topDog nie jest asynchroniczny pomimo wywołania funkcji asynchronicznej.

wprowadź opis obrazu tutaj

EDYCJA: Zdaję sobie sprawę, że wiele razy trzeba zawinąć funkcję asynchroniczną wewnątrz funkcji synchronizacji, gdy znajduje się wewnątrz kontrolera. Oto sztuczka imprezowa w takich sytuacjach:

const getDemSweetDataz = (req, res) => {
    (async () => {
        try{
            res.status(200).json(
                await asyncOperation()
            );
        }
        catch(e){
            res.status(500).json(serviceResponse); //or whatever
        }
    })() //So we defined and immediately called this async function.
}

Wykorzystując to z wywołaniami zwrotnymi, możesz wykonać zawijanie, które nie używa obietnic:

const asyncOperation = () => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{resolve("hi")}, 3000)
    })
}

const asyncFunction = async (callback) => {
    let res = await asyncOperation();
    callback(res);
}

const topDog = () => {
    let callback = (res) => {
        console.log(res);
    };

    (async () => {
        await asyncFunction(callback)
    })()
}

Stosując tę ​​sztuczkę do EventEmittera, możesz uzyskać te same wyniki. Zdefiniuj odbiornik EventEmittera, w którym zdefiniowałem wywołanie zwrotne, i wyemituj zdarzenie, w którym wywołałem wywołanie zwrotne.

user2485309
źródło
1

Nie mogę znaleźć scenariusza, którego nie można rozwiązać za pomocą włókien węzłowych. Podany przykład przy użyciu węzłów-włókien zachowuje się zgodnie z oczekiwaniami. Kluczem jest uruchomienie całego odpowiedniego kodu wewnątrz światłowodu, więc nie trzeba rozpoczynać nowego włókna w przypadkowych pozycjach.

Zobaczmy przykład: Załóżmy, że używasz jakiegoś frameworka, który jest punktem wejścia do twojej aplikacji (nie możesz modyfikować tego frameworka). Ten framework ładuje moduły nodejs jako wtyczki i wywołuje niektóre metody we wtyczkach. Powiedzmy, że ten framework akceptuje tylko funkcje synchroniczne i sam nie używa włókien.

Istnieje biblioteka, której chcesz użyć w jednej ze swoich wtyczek, ale ta biblioteka jest asynchroniczna i nie chcesz jej też modyfikować.

Nie można uzyskać głównego wątku, gdy żadne włókno nie jest uruchomione, ale nadal można tworzyć wtyczki za pomocą włókien! Po prostu utwórz wpis opakowujący, który uruchamia cały framework wewnątrz włókna, abyś mógł wykonać wykonanie z wtyczek.

Wada: Jeśli platforma używa setTimeoutlubPromise s wewnętrznie, to wymknie się z kontekstu włókna. Można to obejść przez szyderczy setTimeout, Promise.theni wszyscy obsługi zdarzeń.

Więc w ten sposób możesz wydobyć włókno do czasu Promise zostanie rozwiązane. Ten kod przyjmuje funkcję asynchroniczną (zwracająca obietnicę) i wznawia działanie włókna po rozwiązaniu obietnicy:

framework-entry.js

console.log(require("./my-plugin").run());

async-lib.js

exports.getValueAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Async Value");
    }, 100);
  });
};

my-plugin.js

const Fiber = require("fibers");

function fiberWaitFor(promiseOrValue) {
  var fiber = Fiber.current, error, value;
  Promise.resolve(promiseOrValue).then(v => {
    error = false;
    value = v;
    fiber.run();
  }, e => {
    error = true;
    value = e;
    fiber.run();
  });
  Fiber.yield();
  if (error) {
    throw value;
  } else {
    return value;
  }
}

const asyncLib = require("./async-lib");

exports.run = () => {
  return fiberWaitFor(asyncLib.getValueAsync());
};

my-entry.js

require("fibers")(() => {
  require("./framework-entry");
}).run();

Po uruchomieniu node framework-entry.jsgo wygeneruje błąd: Error: yield() called with no fiber running. Jeśli uruchomisz node my-entry.js, działa zgodnie z oczekiwaniami.

Tamas Hegedus
źródło
0

Synchronizacja kodu Node.js jest niezbędna w kilku aspektach, takich jak baza danych. Jednak faktyczna zaleta Node.js polega na kodzie asynchronicznym. Ponieważ jest to jeden wątek nieblokujący.

możemy go zsynchronizować używając ważnej funkcjonalności Fibre () Używając await () i defer () wywołujemy wszystkie metody używając await (). następnie zamień funkcje zwrotne na defer ().

Normalny kod asynchroniczny, który wykorzystuje funkcje CallBack.

function add (var a, var b, function(err,res){
       console.log(res);
});

 function sub (var res2, var b, function(err,res1){
           console.log(res);
    });

 function div (var res2, var b, function(err,res3){
           console.log(res3);
    });

Zsynchronizuj powyższy kod za pomocą Fiber (), await () i defer ()

fiber(function(){
     var obj1 = await(function add(var a, var b,defer()));
     var obj2 = await(function sub(var obj1, var b, defer()));
     var obj3 = await(function sub(var obj2, var b, defer()));

});

Mam nadzieję, że to pomoże. Dziękuję Ci

Mohan Ramakrishna
źródło
0

Obecnie ten wzorzec generatora może być rozwiązaniem w wielu sytuacjach.

Oto przykład sekwencyjnych monitów konsoli w nodejs używających funkcji async readline.question:

var main = (function* () {

  // just import and initialize 'readline' in nodejs
  var r = require('readline')
  var rl = r.createInterface({input: process.stdin, output: process.stdout })

  // magic here, the callback is the iterator.next
  var answerA = yield rl.question('do you want this? ', r=>main.next(r))    

  // and again, in a sync fashion
  var answerB = yield rl.question('are you sure? ', r=>main.next(r))        

  // readline boilerplate
  rl.close()

  console.log(answerA, answerB)

})()  // <-- executed: iterator created from generator
main.next()     // kick off the iterator, 
                // runs until the first 'yield', including rightmost code
                // and waits until another main.next() happens
drodsou
źródło
-1

Nie powinieneś patrzeć na to, co dzieje się wokół połączenia, które tworzy włókno, ale raczej na to, co dzieje się wewnątrz włókna. Gdy jesteś w środku włókna, możesz programować w stylu synchronizacji. Na przykład:

function f1 () {
    console.log ('czekaj ...' + nowa data);
    spać (1000);
    console.log ('ok ...' + nowa data);   
}

function f2 () {
    f1 ();
    f1 ();
}

Fiber (function () {
    f2 ();
}).biegać();

Wewnątrz włókna, do którego dzwonisz f1, f2i sleepjakby były zsynchronizowane.

W typowej aplikacji internetowej światłowód zostanie utworzony w programie wysyłającym żądania HTTP. Gdy już to zrobisz, możesz napisać całą logikę obsługi żądań w stylu synchronizacji, nawet jeśli wywołuje ona funkcje asynchroniczne (FS, bazy danych itp.).

Bruno Jouhier
źródło
Dzięki Bruno. Ale co, jeśli potrzebuję stylu synchronizacji w kodzie bootstrap, który musi zostać wykonany, zanim serwer połączy się z portem TCP - na przykład konfiguracja lub dane, które należy odczytać z bazy danych otwartej asynchronicznie? Może skończyło się na zawinięciu całego server.js w Fibre i podejrzewam, że zabije to współbieżność na poziomie całego procesu. Niemniej jest to sugestia, którą warto zweryfikować. Dla mnie idealnym rozwiązaniem powinno być zawinięcie funkcji asynchronicznej, aby zapewnić składnię wywołania synchronizacji i blokować tylko następne wiersze kodu w łańcuchu wywołującym bez poświęcania współbieżności na poziomie procesu.
skrót
Możesz opakować cały kod bootstrap w jedno duże wywołanie Fiber. Współbieżność nie powinna stanowić problemu, ponieważ kod ładowania początkowego zwykle musi zostać ukończony przed rozpoczęciem obsługi żądań. Włókno nie przeszkadza również w uruchomieniu innych włókien: za każdym razem, gdy trafisz na sygnał o wydajności, dajesz szansę innym włóknom (i głównej nici) na uruchomienie.
Bruno Jouhier
Mam plik server.js bootstrap Express opakowany włóknem. Sekwencja wykonywania jest tym, czego szukam, ale to zawijanie nie ma żadnego wpływu na obsługę żądań. Więc myślę, że muszę zastosować to samo opakowanie do KAŻDEGO wysyłającego. W tym momencie zrezygnowałem, ponieważ nie wydaje się, aby pomagało uniknąć globalnego ponownego faktoringu. Moim celem jest zminimalizowanie wpływu na dzwoniącego, gdy metoda pozyskiwania danych zostanie zmieniona z synchronizacji na asynchroniczną w warstwie DAO, a Fibre nadal trochę zabraknie temu wyzwaniu.
skrót
@fred: Nie ma sensu "synchronizować" strumieni zdarzeń, jak w przypadku modułu obsługi żądań - potrzebna byłaby while(true) handleNextRequest()pętla. Owinięcie każdej obsługi żądań w światłowodzie byłoby.
Bergi
@fred: włókna nie pomogą ci zbytnio w Express, ponieważ callback Express nie jest kontynuacją callback (wywołanie zwrotne, które jest zawsze wywoływane dokładnie raz, z błędem lub z wynikiem). Ale włókna rozwiążą piramidę zagłady, gdy masz dużo kodu napisanego na asynchronicznych interfejsach API z wywołaniami zwrotnymi kontynuacji (np. Fs, mongodb i wiele innych).
Bruno Jouhier
-2

Na początku zmagałem się z tym, korzystając z node.js, a async.js to najlepsza biblioteka, jaką znalazłem, aby pomóc ci sobie z tym poradzić. Jeśli chcesz pisać kod synchroniczny z węzłem, podejście jest takie.

var async = require('async');

console.log('in main');

doABunchOfThings(function() {
  console.log('back in main');
});

function doABunchOfThings(fnCallback) {
  async.series([
    function(callback) {
      console.log('step 1');
      callback();
    },
    function(callback) {
      setTimeout(callback, 1000);
    },
    function(callback) {
      console.log('step 2');
      callback();
    },
    function(callback) {
      setTimeout(callback, 2000);
    },
    function(callback) {
      console.log('step 3');
      callback();
    },
  ], function(err, results) {
    console.log('done with things');
    fnCallback();
  });
}

ten program ZAWSZE wyprodukuje następujące ...

in main
step 1
step 2
step 3
done with things
back in main
Michael Connor
źródło
2
asyncdziała w twoim przykładzie b / c to main, co nie dba o rozmówcę. Wyobraź sobie, że cały kod jest opakowany w funkcję, która ma zwracać wynik jednego z wywołań funkcji asynchronicznej. Można łatwo sprawdzić, czy nie działa, dodając console.log('return');na końcu kodu. W takim przypadku wyjście returnnastąpi po, in mainale przed step 1.
skrót
-11

Javascript jest językiem jednowątkowym, nie chcesz blokować całego serwera! Kod asynchroniczny eliminuje warunki wyścigu, jawnie określając zależności.

Naucz się kochać kod asynchroniczny!

Przyjrzyj się promisesasynchronicznemu kodowi bez tworzenia piramidy piekła zwrotnego. Polecam bibliotekę promiseQ dla node.js

httpGet(url.parse("http://example.org/")).then(function (res) {
    console.log(res.statusCode);  // maybe 302
    return httpGet(url.parse(res.headers["location"]));
}).then(function (res) {
    console.log(res.statusCode);  // maybe 200
});

http://howtonode.org/promises

EDYCJA: to jest zdecydowanie moja najbardziej kontrowersyjna odpowiedź, węzeł ma teraz słowo kluczowe yield, które pozwala traktować kod asynchroniczny tak, jakby był synchroniczny. http://blog.alexmaccaw.com/how-yield-will-transform-node

roo2
źródło
1
Promise tylko przeformułowuje parametr wywołania zwrotnego, zamiast zamieniać funkcję w synchronizację.
skrót
2
nie chcesz, aby była synchronizowana, albo cały serwer zostanie zablokowany! stackoverflow.com/questions/17959663/…
roo2
1
Pożądane jest wywołanie synchronizacji bez blokowania innych zdarzeń, takich jak inne żądanie obsługiwane przez Node.js. Funkcja Sync z definicji oznacza tylko, że nie powróci do wywołującego, dopóki nie zostanie wygenerowany wynik (a nie tylko obietnica). Nie wyklucza wstępnie serwera z obsługi innych zdarzeń, gdy połączenie jest zablokowane.
skrót
@fred: Myślę, że nie dotrzymujesz obietnic . Nie są po prostu abstrakcją wzorca obserwatora, ale zapewniają sposób łączenia i komponowania akcji asynchronicznych.
Bergi
1
@Bergi, często używam obietnic i dokładnie wiem, co ona robi. W efekcie wszystko, co osiągnięto, to rozbicie pojedynczego wywołania funkcji asynchronicznej na wiele wywołań / instrukcji. Ale nie zmienia to wyniku - gdy wywołujący powraca, nie może zwrócić wyniku funkcji asynchronicznej. Sprawdź przykład, który zamieściłem w JSFiddle. Obiekt wywołujący w tym przypadku jest funkcją AnticipatedSyncFunction, a funkcją asynchroniczną jest setTimeout. Jeśli możesz odpowiedzieć na moje wyzwanie za pomocą obietnicy, pokaż mi.
skrót