Eşzamansız işlev çağrılarını Node.js veya Javascript'te bir eşitleme işlevine nasıl sarabilirim?


122

Bir işlevi açığa çıkaran bir kitaplık tuttuğunuzu varsayalım getData. Kullanıcılarınız gerçek verileri almak için onu çağırır:
var output = getData();
Başlık altında veriler bir dosyaya kaydedilir, böylece getDatayerleşik Node.js kullanarak uygulayabilirsiniz fs.readFileSync. Her ikisi de açıktır getDatave fs.readFileSyncsenkronizasyon işlevleridir. Bir gün, temeldeki veri kaynağını yalnızca eşzamansız olarak erişilebilen MongoDB gibi bir depoya geçirmeniz söylendi. Ayrıca kullanıcılarınızı kızdırmaktan kaçınmanız söylendi, getDataAPI yalnızca bir söz verecek veya bir geri arama parametresi talep edecek şekilde değiştirilemez. Her iki gereksinimi nasıl karşılıyorsunuz?

Geri arama / söz kullanan asenkron işlev, JavasSript ve Node.js'nin DNA'sıdır. Önemsiz olmayan herhangi bir JS uygulamasına muhtemelen bu kodlama stiline nüfuz edilmiştir. Ancak bu uygulama, sözde geri arama piramidine kolayca yol açabilir. Daha da kötüsü, çağrı zincirindeki herhangi bir arayıcıdaki herhangi bir kod zaman uyumsuz işlevin sonucuna bağlıysa, bu kodun da geri arama işlevine sarılması gerekir, bu da arayana bir kodlama stili kısıtlaması getirir. Zaman zaman, devasa global yeniden faktörlemeden kaçınmak için bir eşzamansız işlevi (genellikle bir 3. taraf kitaplığında sağlanır) bir eşitleme işlevine kapsülleme ihtiyacını buluyorum. Bu konuda bir çözüm aramak genellikle Node Fibers ile sonuçlandıveya ondan türetilen npm paketleri. Ancak Fibers karşılaştığım sorunu çözemiyor. Fibers'in yazarının sağladığı örnek bile eksikliği gösterdi:

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

Gerçek çıktı:

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)

Fiber işlevi, eşzamansız işlev uykusunu gerçekten eşzamanlı hale getiriyorsa, çıktı şu şekilde olmalıdır:

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

JSFiddle'da başka bir basit örnek oluşturdum ve beklenen çıktıyı verecek kod aradım . Yalnızca Node.js'de çalışan bir çözümü kabul edeceğim, böylece JSFiddle'da çalışmamasına rağmen herhangi bir npm paketine ihtiyaç duymakta özgürsünüz.


2
Eşzamansız işlevler Düğümde hiçbir zaman eşzamanlı hale getirilemez ve yapabilseler bile yapmamalısınız. Sorun öyledir ki, fs modülünde dosya sistemine eşzamanlı ve eşzamansız erişim için tamamen ayrı işlevler görebilirsiniz. Yapabileceğiniz en iyi şey, eşzamansız görüntünün vaatler veya eşdizimlerle (ES6'daki oluşturucular) görünümünü maskelemektir. Geri arama piramitlerini yönetmek için, bir işlev çağrısında tanımlamak yerine onlara adlar verin ve eşzamansız kitaplık gibi bir şey kullanın.
qubyte

8
Dandavis'e göre, zaman uyumsuz uygulama ayrıntısını çağrı zincirinde kabarcıklar oluşturur ve bazen genel yeniden düzenlemeyi zorlar. Bu, modülerleştirme ve muhafazanın önemli olduğu karmaşık bir uygulama için zararlı ve hatta felakettir.
kısaltması

4
"Kıyametin geri çağırma piramidi" sadece sorunun temsilidir. Promise, onu gizleyebilir veya gizleyebilir, ancak gerçek zorluğu çözemez: Bir asenkron işlevin arayanı, eşzamansız işlevin sonuçlarına bağlıysa, geri aramayı kullanmak zorundadır ve onu çağıran da vb. sadece uygulama ayrıntıları nedeniyle arayan.
kısalt

1
@abbr: Deasync modülü için teşekkürler, probleminizin açıklaması tam olarak aradığım şey ve uygulanabilir herhangi bir çözüm bulamadım. Jeneratörler ve yinelenenlerle uğraştım ama sizinle aynı sonuçlara vardım.
Kevin Jhangiani

2
Eşzamansız bir işlevi eşzamanlı olmaya zorlamanın neredeyse hiçbir zaman iyi bir fikir olmadığını belirtmek gerekir . Neredeyse her zaman , işlevin eşzamansızlığını sağlam tutan daha iyi bir çözüme sahip olurken, aynı etkiyi elde etmeye devam edersiniz (sıralama, değişken ayarı vb. Gibi).
Madara'nın Hayalet

Yanıtlar:


105

deasync , JavaScript katmanında Node.js olay döngüsünü çağırarak bir engelleme mekanizmasıyla uygulanan eşzamansız işlevi senkronizasyona dönüştürür. Sonuç olarak, deasync yalnızca sonraki kodun tüm iş parçacığını engellemeden veya meşgul beklemeye maruz kalmadan çalışmasını engeller. Bu modülle, işte jsFiddle meydan okumasının cevabı:

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)

(sorumluluk reddi: adlı kitabın ortak yazarıyım deasync. Modül, bu soruyu gönderdikten sonra oluşturuldu ve uygulanabilir bir öneri bulamadı.)


Başka birinin bunda şansı oldu mu? Çalışmasını sağlayamıyorum.
newman

3
Düzgün çalışmasını sağlayamıyorum. Daha fazla kullanılmasını istiyorsanız, bu modül için belgelerinizi geliştirmelisiniz. Yazarların modülü kullanmanın sonuçlarını tam olarak bildiğinden şüpheliyim ve eğer yaparlarsa, kesinlikle bunları belgelemezler.
Alexander Mills

5
Şimdiye kadar github sorun izleyicisinde belgelenen bir onaylanmış sorun var. Sorun, Düğüm v0.12'de düzeltildi. Bildiğim geri kalanı, belgelemeye değmeyen, asılsız spekülasyonlar. Sorununuzun deasync'den kaynaklandığına inanıyorsanız, kendi kendine yeten, kopyalanabilir bir senaryo yayınlayın ve ben ilgileneceğim.
kısalt

Kullanmaya çalıştım ve senaryomda bazı iyileştirmeler aldım ama yine de tarih konusunda şansım olmadı. Kodu aşağıdaki gibi değiştirdim: 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); ve tarih çıktısında 3 saniye farklı görmeyi bekliyorum!
Alex

@abbr bu tarayıcı tarafından doğrulanabilir ve düğüm bağımlılığı olmadan kullanılabilir mi>
Gandhi

5

Ayrıca bir npm senkronizasyon modülü de vardır. Sorguyu yürütme sürecini senkronize etmek için kullanılır.

Paralel sorguları eşzamanlı olarak çalıştırmak istediğinizde, düğüm bunu yapmak için kısıtlar çünkü yanıt için asla beklemez. ve senkronizasyon modülü bu tür bir çözüm için çok mükemmeldir.

Basit 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);
                }
            });
        });
    }

referans bağlantısı: https://www.npmjs.com/package/sync


4

İşlev Fiber gerçekten eşzamansız işlev uykusunu eşzamanlı hale getiriyorsa

Evet. Fiberin içinde, fonksiyon kayıt yapmadan önce bekler ok. Fiberler eşzamansız işlevleri eşzamanlı yapmazlar, ancak eşzamanlı olmayan işlevler kullanan eşzamanlı görünümlü kodların yazılmasına izin verir ve sonra bir Fiber.

Zaman zaman, büyük çaplı küresel yeniden faktörlemeden kaçınmak için bir eşzamansız işlevi bir senkronizasyon işlevine kapsülleme ihtiyacını buluyorum.

Yapamazsın. Eşzamansız kodu eşzamanlı yapmak imkansızdır. Bunu global kodunuzda tahmin etmeniz ve baştan itibaren asenkron tarzda yazmanız gerekecek. Global kodu bir fibere sarmanız, sözler, vaat oluşturucular veya basit geri aramalar kullanmanız tercihlerinize bağlıdır.

Amacım, veri toplama yöntemi senkronizasyondan zaman uyumsuzluğa değiştirildiğinde arayan üzerindeki etkiyi en aza indirmektir.

Hem sözler hem de lifler bunu yapabilir.


1
bu, Node.js ile yapabileceğiniz en kötü şey KESİNLİKLE: "eşzamansız işlevler kullanan ve sonra eşzamansız olarak çalışan eşzamanlı görünümlü kod." API'niz bunu yaparsa, hayatları mahvedersiniz. zaman uyumsuzsa, bir geri arama gerektirmeli ve geri arama sağlanmadıysa bir hata atmalıdır. Amacınız insanları kandırmak değilse, bu bir API oluşturmanın en iyi yoludur.
Alexander Mills

@AlexMills: Evet, bu gerçekten korkunç olurdu . Ancak neyse ki bu bir API'nin yapabileceği bir şey değildir. Eşzamansız bir API'nin her zaman bir geri aramayı kabul etmesi / bir söz vermesi / bir fiber içinde çalışmayı beklemesi gerekir - olmadan çalışmaz. Afaik, fiberler çoğunlukla engelleyen ve eşzamanlılığı olmayan, ancak asenkron API'leri kullanmak isteyen quick'n'dirty komut dosyalarında kullanıldı; Tıpkı düğümde olduğu gibi, bazen senkronize fsyöntemleri kullandığınız durumlar vardır .
Bergi

2
Genelde düğümü severim. Özellikle de saf js yerine typcript kullanabilirsem. Ancak yaptığınız her şeye nüfuz eden ve tek bir eşzamansız çağrı yapmaya karar verir vermez çağrı zincirindeki her işlevi kelimenin tam anlamıyla etkileyen bu eşzamansız saçmalık, gerçekten ... gerçekten nefret ettiğim bir şey. Async api bulaşıcı bir hastalık gibidir, bir çağrı tüm kod tabanınıza bulaşarak sizi sahip olduğunuz tüm kodu yeniden yazmaya zorlar. Birinin bunun iyi bir şey olduğunu nasıl iddia edebileceğini gerçekten anlamıyorum .
Kris

@Kris Node, hızlı ve basit olduğu için IO görevleri için asenkron bir model kullanır . Pek çok şeyi eşzamanlı olarak da yapabilirsiniz, ancak eşzamanlı olarak hiçbir şey yapamayacağınız için engelleme yavaştır - iş parçacıkları seçmediğiniz sürece, bu da her şeyi karmaşık hale getirir.
Bergi

@Bergi Manifestoyu okudum, böylece argümanları biliyorum. Ancak mevcut kodunuzu eşzamanlı olmayan o ilk api çağrısına ulaştığınız anda eşzamanlı olmayan kod olarak değiştirmek kolay değildir . Her şey kırılır ve her bir kod satırının incelenmesi gerekir. Kodunuz önemsiz değilse garanti ederim ... her şeyi asenkron deyime dönüştürdükten sonra dönüştürmek ve tekrar çalıştırmak biraz zaman alacak.
Kris

2

Sözleri kullanmalısın:

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);
    });
}

Ok işlevi tanımlarını daha çok seviyorum. Ancak "() => {...}" biçimindeki herhangi bir dizge, "function () {...}" olarak da yazılabilir

Dolayısıyla topDog, eşzamansız bir işlevi çağırmasına rağmen eşzamansız değildir.

görüntü açıklamasını buraya girin

DÜZENLEME: Zaman uyumsuz bir işlevi bir eşzamanlama işlevi içinde sarmalamanız gerektiğinin çoğu zaman bir denetleyicinin içinde olduğunun farkındayım. Bu durumlar için, işte bir parti numarası:

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.
}

Bunu geri aramalarla kullanarak, vaatleri kullanmayan bir sarmalama yapabilirsiniz:

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)
    })()
}

Bu numarayı bir EventEmiter'a uygulayarak aynı sonuçları elde edebilirsiniz. Geri aramayı tanımladığım EventEmitter dinleyicisini tanımlayın ve geri aramayı çağırdığım olayı yayınlayın.


1

Düğüm lifleri kullanılarak çözülemeyen bir senaryo bulamıyorum. Düğüm liflerini kullanarak sağladığınız örnek beklendiği gibi davranıyor. Önemli olan tüm ilgili kodu bir fiber içinde çalıştırmaktır, böylece rastgele pozisyonlarda yeni bir fibere başlamak zorunda kalmazsınız.

Bir örnek görelim: Uygulamanızın giriş noktası olan bazı çerçeve kullandığınızı varsayalım (bu çerçeveyi değiştiremezsiniz). Bu çerçeve nodejs modüllerini eklenti olarak yükler ve eklentiler üzerinde bazı yöntemleri çağırır. Bu çerçevenin yalnızca eşzamanlı işlevleri kabul ettiğini ve lifleri kendi başına kullanmadığını söyleyelim.

Eklentilerinizden birinde kullanmak istediğiniz bir kitaplık var, ancak bu kitaplık eşzamansızdır ve onu değiştirmek de istemezsiniz.

Hiçbir fiber çalışmadığında ana iş parçacığı verilemez, ancak yine de fiber kullanarak eklentiler oluşturabilirsiniz! Tüm çerçeveyi bir fiber içinde başlatan bir sarmalayıcı girişi oluşturun, böylece eklentilerden yürütmeyi sağlayabilirsiniz.

Dezavantajı: Çerçeve dahili olarak kullanıyorsa setTimeoutveya kullanıyorsa Promise, fiber bağlamdan kaçacaktır. Bu alay tarafından çalışılan setTimeout, Promise.thenve tüm olay işleyicileri.

Yani a Promiseçözülene kadar bu şekilde lif elde edebilirsiniz . Bu kod, zaman uyumsuz (Promise dönen) işlevi alır ve söz çözüldüğünde fiberi devam ettirir:

Çerçeve-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();

Eğer çalıştırdığınızda node framework-entry.jsbir hata atar: Error: yield() called with no fiber running. Çalıştırırsanız node my-entry.jsbeklendiği gibi çalışır.


0

Node.js kod senkronizasyonunun yapılması, veritabanı gibi birkaç açıdan önemlidir. Ancak Node.js'nin gerçek avantajı eşzamansız kodda yatmaktadır. Tek iş parçacığı tıkanmaz olduğu için.

önemli işlevselliği kullanarak senkronize edebiliriz Fiber () Kullanın await () ve defer () await () kullanarak tüm yöntemleri çağırırız. daha sonra geri arama işlevlerini defer () ile değiştirin.

Normal Eşzamansız kod Bu, CallBack işlevlerini kullanır.

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);
    });

Fiber (), await () ve defer () kullanarak yukarıdaki kodu senkronize edin

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()));

});

Umarım bu yardımcı olacak. Teşekkür ederim


0

Günümüzde bu jeneratör modeli birçok durumda bir çözüm olabilir.

Burada, eşzamansız readline.question işlevini kullanan düğümlerdeki sıralı konsol istemlerinin bir örneği:

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

-1

Elyafı oluşturan çağrı etrafında ne olduğuna değil , elyafın içinde ne olduğuna bakmalısınız . Fiberin içine girdikten sonra senkron tarzda programlayabilirsiniz. Örneğin:

function f1 () {
    console.log ('bekle ...' + yeni Tarih);
    uyku (1000);
    console.log ('tamam ...' + yeni Tarih);   
}

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

Lif (işlev () {
    f2 ();
}).Çalıştırmak();

Lif İçinde Aramak f1, f2ve sleepsanki onlar senkronizasyon idi.

Tipik bir web uygulamasında, Fiber'i HTTP istek dağıtıcınızda oluşturacaksınız. Bunu yaptıktan sonra, tüm istek işleme mantığınızı, eşzamansız işlevleri (fs, veritabanları, vb.) Çağırsa bile, eşitleme stilinde yazabilirsiniz.


Teşekkürler Bruno. Peki ya sunucu tcp bağlantı noktasına bağlanmadan önce çalıştırılması gereken önyükleme kodunda senkronizasyon stiline ihtiyacım olursa - yapılandırma veya eşzamansız açılan db'den okunması gereken veriler gibi? Server.js'nin tamamını Fiber'e sarmalamış olabilirim ve bunun tüm süreç düzeyinde eşzamanlılığı öldüreceğinden şüpheleniyorum. Yine de, doğrulanmaya değer bir öneri. Bana göre ideal çözüm, bir senkronizasyon çağrısı sözdizimi sağlamak için zaman uyumsuz bir işlevi sarabilmeli ve süreç düzeyinde eşzamanlılıktan ödün vermeden yalnızca arayan zincirindeki sonraki kod satırlarını engelleyebilmelidir.
kısaltması

Tüm önyükleme kodunuzu tek bir büyük Fiber çağrısının içine alabilirsiniz. Eşzamanlılık bir sorun olmamalıdır çünkü önyükleme kodunun, istekleri sunmaya başlamadan önce genellikle tamamlanması gerekir. Ayrıca, bir lif diğer liflerin akmasını engellemez: Bir verim çağrısına her ulaştığınızda, diğer liflere (ve ana ipliğe) koşma şansı verirsiniz.
Bruno Jouhier

Express bootstrap dosyasını server.js'yi fiber ile sarmaladım. Yürütme sırası aradığım şeydir, ancak bu sarmalamanın istek işleyicisi üzerinde herhangi bir etkisi yoktur. Bu yüzden, aynı sargıyı HER dağıtıcıya uygulamak zorundayım. Bu noktada pes ettim çünkü küresel yeniden faktörlemeden kaçınmaya yardımcı olmak için daha iyi bir şey yapmıyor gibi görünüyor. Amacım, veri toplama yöntemi DAO katmanında eşitlemeden eşzamansız hale getirildiğinde ve Fiber hala bu zorluğun biraz gerisinde kaldığında arayan üzerindeki etkiyi en aza indirmektir.
kısalt

@fred: İstek işleyici gibi olay akışlarını "senkronize etmek" pek mantıklı değil - bir while(true) handleNextRequest()döngüye sahip olmanız gerekir . Her istek işleyicisini bir fiberde sarmak olur.
Bergi

@fred: Express' geri arama çünkü lifler Express ile size çok yardımcı olmayacaktır değil bir devam geri arama (her zaman tam olarak bir kez çağrılan bir geri arama bir hatayla veya sonuçla ya). Ancak, süreklilik geri çağırmalarıyla (fs, mongodb ve diğerleri gibi) zaman uyumsuz API'lerin üzerine yazılmış çok sayıda kodunuz olduğunda, lifler kıyamet piramidini çözecektir.
Bruno Jouhier

-2

İlk başta node.js ile bununla uğraştım ve async.js, bununla başa çıkmanıza yardımcı olmak için bulduğum en iyi kitaplık. Düğüm ile eşzamanlı kod yazmak istiyorsanız, yaklaşım bu şekildedir.

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();
  });
}

bu program DAİMA aşağıdakileri üretecektir ...

in main
step 1
step 2
step 3
done with things
back in main

2
asyncörneğinizde çalışır, b / c bu main, arayanla ilgilenmez. Tüm kodunuzun, eşzamansız işlev çağrılarınızdan birinin sonucunu döndürmesi beklenen bir işleve sarıldığını hayal edin. console.log('return');Kodunuzun sonuna eklenerek çalışmadığı kolayca ispat edilebilir . Böyle bir durumda çıktısı returnsonra in mainama önce olacaktır step 1.
kısaltması

-11

Javascript tek iş parçacıklı bir dildir, tüm sunucunuzu engellemek istemezsiniz! Zaman uyumsuz kod, bağımlılıkları açık hale getirerek yarış koşullarını ortadan kaldırır.

Eşzamansız kodu sevmeyi öğrenin!

Bir promisesgeri arama cehennemi piramidi oluşturmadan zaman uyumsuz koda bir göz atın . Node.js için promiseQ kitaplığını öneririm

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

DÜZENLEME: Bu, açık ara en tartışmalı cevabım, node'un artık verim anahtar kelimesi var, bu da eşzamansız kodu eşzamanlıymış gibi ele almanıza izin veriyor. http://blog.alexmaccaw.com/how-yield-will-transform-node


1
Promise, işlevi senkronize hale getirmek yerine yalnızca geri arama parametresini yeniden ifade eder.
kısalt

2
yuu senkronize olmasını istemezseniz sunucunuzun tamamı engellenir! stackoverflow.com/questions/17959663/…
roo2

1
Arzu edilen şey, Node.js tarafından işlenen başka bir istek gibi diğer olayları engellemeden bir senkronizasyon çağrısıdır. Yalnızca tanımı gereği bir Eşitleme işlevi, sonuç üretilinceye kadar (yalnızca bir söz değil) arayan kişiye geri dönmeyeceği anlamına gelir. Çağrı engellendiğinde sunucunun diğer olayları işlemesini önceden dışlamaz.
kısaltması

@fred: Bence sözlerin noktasını kaçırıyorsun . Bunlar basit bir gözlemci kalıbı soyutlaması değildir, ancak eşzamansız eylemleri zincirlemek ve oluşturmak için bir yol sağlarlar.
Bergi

1
@Bergi, söz vermeyi çok kullanıyorum ve tam olarak ne işe yaradığını biliyorum. Etkili olarak tek bir eşzamansız işlev çağrısını birden çok çağrıya / ifadeye bölmek. Ancak sonucu değiştirmez - arayan geri döndüğünde, eşzamansız işlevin sonucunu döndüremez. JSFiddle'da yayınladığım örneğe bakın. Bu durumda arayan, AnticipatedSyncFunction işlevidir ve zaman uyumsuz işlev ise setTimeout'tur. Sözünü kullanarak meydan okumama cevap verebilirseniz, lütfen bana gösterin.
kısalt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.