JavaScript Q кітапханасында синхронды уәде ете аламын ба?

Мен келесідей нәрсе жасағым келеді:

delay( 2500 )
  .then( function() { console.log( "Step 1 done" ) } )
  .then( delay( 7500 ) )
  .then( function() { console.log( "Step 2 done" ) } );

Сондықтан кідірістің жүзеге асырылуы бірнеше рет:

function delay( ms ) {
  var deferred = Q.defer();
  setTimeout( deferred.resolve, ms );
  return deferred.promise;
}

Бірақ жоғарыда көрсетілген node.js ішіне жүгірсем, аламын:

... delay of 2500ms
Step 1 done
Step 2 done
... delay of ~7500ms

Мен көретінімді емес,

... delay of 2500ms
Step 1 done
... delay of 7500ms
Step 2 done

https://github.com/kriskowal/q/wiki/Examples-Gallery мысалында берілген. Уәде функциясымен байланысы бар синхронды функциялардың кез келген мысалын таба алмаймын (ешқандай кері байланыссыз мән қайтаратын функциялар).

Асинхронды уәделермен синхронды әрекеттермен араласуға қандай да бір идеялар?

Мен тырысамын:

function synchronousPromise() {
  var deferred = Q.defer();
  console.log( "Synchronous function call" );
  deferred.resolve();
  return deferred.promise;
}

delay( 2500 )
  .then( function(){synchronousPromise()} )
  .then( function(){delay( 7500 )} )
  .then( function(){synchronousPromise()} );

Және бұл нәтиже:

... delay of 2500ms
Time now is 2013-06-20
Time now is 2013-06-20
... delay of 7500ms

.. мен әлі де қол жеткізуге тырысатын емеспін.

15
Бірінші және екінші мысалдарда жұмыс істейтін @FelixKling! Сіздің жауапыңызды қабылдаймын.
қосылды автор PP., көзі
Бірінші және екінші мысалдарда жұмыс істейтін @FelixKling! Сіздің жауапыңызды қабылдаймын.
қосылды автор PP., көзі
Бірінші мысалда .then (delay (7500)) орнына .then (function() {return delay (7500);
қосылды автор Felix Kling, көзі
Енді сіз кешіктірілу уақытын көрсетпестен қол жеткізе аламын жауап .
қосылды автор Remo H. Jansen, көзі
Енді сіз кешіктірілу уақытын көрсетпестен қол жеткізе аламын жауап .
қосылды автор Remo H. Jansen, көзі

6 жауаптар

Кері қоңырауларды тізгіңіз келсе, қайтаруға керек жаңа уәде нысанын кері шақыру. Бірінші мысалда сіз жазасыз

.then( delay( 7500 ) )

бұл функция емес, .then -ге уәде беру нысанын жібергеніңізді білдіреді. Promise/A + ұсынысы бойынша (Q сәйкес), барлық функционалды емес дәлелдерді елемеу керек. Осылайша, негізінен, сіз жай ғана жазу сияқты:

delay( 2500 )
  .then( function() { console.log( "Step 1 done" ) } )
  .then( function() { console.log( "Step 2 done" ) } );

Оның орнына delay деп аталатын функцияны беріңіз және уәде нысанын қайтарады:

delay( 2500 )
  .then( function() { console.log( "Step 1 done" ); } ) 
  .then( function() { return delay( 7500 ); } )
  .then( function() { console.log( "Step 2 done" ); } );

Енді екінші кері қоңырау екінші қайтару кезінде delay арқылы қайтарылған уәде нысаны шешілгеннен кейін ғана шақырылады.

13
қосылды

Кері қоңырауларды тізгіңіз келсе, қайтаруға керек жаңа уәде нысанын кері шақыру. Бірінші мысалда сіз жазасыз

.then( delay( 7500 ) )

бұл функция емес, .then -ге уәде беру нысанын жібергеніңізді білдіреді. Promise/A + ұсынысы бойынша (Q сәйкес), барлық функционалды емес дәлелдерді елемеу керек. Осылайша, негізінен, сіз жай ғана жазу сияқты:

delay( 2500 )
  .then( function() { console.log( "Step 1 done" ) } )
  .then( function() { console.log( "Step 2 done" ) } );

Оның орнына delay деп аталатын функцияны беріңіз және уәде нысанын қайтарады:

delay( 2500 )
  .then( function() { console.log( "Step 1 done" ); } ) 
  .then( function() { return delay( 7500 ); } )
  .then( function() { console.log( "Step 2 done" ); } );

Енді екінші кері қоңырау екінші қайтару кезінде delay арқылы қайтарылған уәде нысаны шешілгеннен кейін ғана шақырылады.

13
қосылды

Google ұқсас мәселе бойынша жұмыс істеген кезде маған осында әкелді (бірақ Крис Ковалдың Q-ын пайдаланып), мен өте төмен құрылымды аяқтадым:

var chain = [
  doNext(delay, 2500),
  doNext(console.log, "Step 1 done"),
  doNext(delay, 7500),
  doNext(console.log, "Step 2 done")
];

doInOrder(chain);

Негіздеме - тек 12 жол, және, бәлкім, басқа уәде кітапханаларына бейімделуі мүмкін:

var Q = require('q');

function doNext(fn /* , arguments */){
  var args =  Array.prototype.splice.call(arguments, 1);
  return function(prevRetVal){
   //For my needs I didn't need the results from previous fns
    return fn.apply(null, args)
  }
}

function doInOrder(doNexters, init){
  return doNexters.reduce(Q.when, init);
}
3
қосылды

Google ұқсас мәселе бойынша жұмыс істеген кезде маған осында әкелді (бірақ Крис Ковалдың Q-ын пайдаланып), мен өте төмен құрылымды аяқтадым:

var chain = [
  doNext(delay, 2500),
  doNext(console.log, "Step 1 done"),
  doNext(delay, 7500),
  doNext(console.log, "Step 2 done")
];

doInOrder(chain);

Негіздеме - тек 12 жол, және, бәлкім, басқа уәде кітапханаларына бейімделуі мүмкін:

var Q = require('q');

function doNext(fn /* , arguments */){
  var args =  Array.prototype.splice.call(arguments, 1);
  return function(prevRetVal){
   //For my needs I didn't need the results from previous fns
    return fn.apply(null, args)
  }
}

function doInOrder(doNexters, init){
  return doNexters.reduce(Q.when, init);
}
3
қосылды

Егер сіз Babel немесе TypeScript бағдарламасымен жұмыс істесеңіз, сіз ES6 генераторларын пайдалана аласыз:

  'use strict';

  let asyncTask =() =>
    new Promise(resolve => {
      let delay = Math.floor(Math.random() * 1000);

      setTimeout(function() {
        resolve(delay);
      }, delay);
    });

  let makeMeLookSync = fn => {
    let iterator = fn();
    let loop = result => {
      !result.done && result.value.then(res =>
        loop(iterator.next(res)));
    };

    loop(iterator.next());
  };

  makeMeLookSync(function*() {
    let result = yield asyncTask();

    console.log(result);
  });
0
қосылды

Егер сіз Babel немесе TypeScript бағдарламасымен жұмыс істесеңіз, сіз ES6 генераторларын пайдалана аласыз:

  'use strict';

  let asyncTask =() =>
    new Promise(resolve => {
      let delay = Math.floor(Math.random() * 1000);

      setTimeout(function() {
        resolve(delay);
      }, delay);
    });

  let makeMeLookSync = fn => {
    let iterator = fn();
    let loop = result => {
      !result.done && result.value.then(res =>
        loop(iterator.next(res)));
    };

    loop(iterator.next());
  };

  makeMeLookSync(function*() {
    let result = yield asyncTask();

    console.log(result);
  });
0
қосылды