Sözlerin onFulfilled için birden fazla argümanı olabilir mi?


127

Buradaki özellikleri takip ediyorum ve onFulfilled'in birden çok bağımsız değişkenle çağrılmasına izin verip vermediğinden emin değilim. Örneğin:

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled('arg1', 'arg2');
})

öyle ki benim kodum:

promise.then(function(arg1, arg2){
    // ....
});

ikisini de alacaktı arg1ve arg2?

Herhangi bir vaat uygulamasının bunu nasıl yaptığı umurumda değil, vaatler için w3c şartnamesini yakından takip etmek istiyorum.


Bir ipucu olarak, github.com/then/promise (bir barebone uygulamasıdır) kullanmanın aslında 2. argümanı sağlamadığını gösterdiğini
buldum

2
Bluebird'ü .spread ile kullanmak istiyorsunuz. - ayrıca, teknik özellikleri önemsemeyi bırakın, teknik özellik tamamen uygulamalar arasında birlikte çalışmayla ilgilidir ve tasarım gereği minimumdur.
Benjamin Gruenbaum

Yanıtlar:


130

Buradaki özellikleri takip ediyorum ve onFulfilled'in birden çok bağımsız değişkenle çağrılmasına izin verip vermediğinden emin değilim.

Hayır, yalnızca ilk parametre promise yapıcısında çözünürlük değeri olarak değerlendirilecektir. Bir nesne veya dizi gibi bileşik bir değerle çözümleyebilirsiniz.

Herhangi bir vaat uygulamasının bunu nasıl yaptığı umurumda değil, vaatler için w3c şartnamesini yakından takip etmek istiyorum.

Yanlış olduğuna inandığım yer burası. Spesifikasyon minimum olacak şekilde tasarlanmıştır ve vaat edilen kitaplıklar arasında birlikte çalışacak şekilde oluşturulmuştur. Buradaki fikir, örneğin DOM geleceklerinin güvenilir bir şekilde kullanabileceği ve kitaplıkların tüketebileceği bir alt kümeye sahip olmaktır. Söz uygulamaları .spreadbir süredir istediğinizi yapın . Örneğin:

Promise.try(function(){
    return ["Hello","World","!"];
}).spread(function(a,b,c){
    console.log(a,b+c); // "Hello World!";
});

İle Bluebird . Bu işlevselliği istiyorsanız bir çözüm, onu çoklu doldurmaktır.

if (!Promise.prototype.spread) {
    Promise.prototype.spread = function (fn) {
        return this.then(function (args) {
            return Promise.all(args); // wait for all
        }).then(function(args){
         //this is always undefined in A+ complaint, but just in case
            return fn.apply(this, args); 
        });
    };
}

Bu şunları yapmanızı sağlar:

Promise.resolve(null).then(function(){
    return ["Hello","World","!"]; 
}).spread(function(a,b,c){
    console.log(a,b+c);    
});

Yerli vaatlerle keman . Veya tarayıcılarda artık (2018) yaygın olan spread'i kullanın:

Promise.resolve(["Hello","World","!"]).then(([a,b,c]) => {
  console.log(a,b+c);    
});

Veya beklerken:

let [a, b, c] = await Promise.resolve(['hello', 'world', '!']);

2
Diğer kütüphanelerin de (Q .spreadgibi) Bluebird gibi desteklediğine dikkat edin - spesifikasyonda olmamasının nedeni, kod ve kütüphaneler arasında birlikte çalışmayı sağlamak için spesifikasyonu minimum tutmanın gerçekten büyük bir mesele olmasıdır .
Benjamin Gruenbaum

İkinci not - bazı şeker kitaplıklarının sağlaması için Promise.allsadece işlevi uygulamadan önce diziyi çağırmak isteyebilirsiniz .then. Zorunlu değil ama sevimli.
Benjamin Gruenbaum

1
Promies.all, uygulamanız için zorunludur, ancak uygulamayı şu şekilde değiştirebilirsinizreturn Promise.all(args).then(function(args){return fn.apply(this, args);})
Esailija

14
spreadgeçici bir noktadır. ES6, yok etme ve dinlenme / yayılma operatörünü sunar, bu da spreadtamamen ihtiyacını ortadan kaldırır . .then(([a, b, c]) => {})
Kris Kowal

3
@KrisKowal .spread () işlevinin örtük olarak .all () işlevini yaptığını, ancak ES6 bozucu sözdiziminin bunu yapmadığını unutmayın -> bluebirdjs.com/docs/api/spread.html
Gomino

66

E6 yıkımını kullanabilirsiniz:

Nesne yok etme:

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled({arg1: value1, arg2: value2});
})

promise.then(({arg1, arg2}) => {
    // ....
});

Dizi bozma:

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled([value1, value2]);
})

promise.then(([arg1, arg2]) => {
    // ....
});

3
Bu cevapla bir örnek güzel ve faydalı olacaktır !
Rahul Verma

19

Bir vaadin yerine getirilme değeri, bir fonksiyonun dönüş değeri ile paraleldir ve bir vaadin reddedilme nedeni, bir fonksiyonun atılan istisnası ile paraleldir. İşlevler birden fazla değer döndüremez, bu nedenle vaatler 1'den fazla yerine getirme değerine sahip olmamalıdır.


4

ES6 Promise spesifikasyonunu ve standart vaat spesifikasyonunu okurken söyleyebildiğim kadarıyla, bir uygulamanın bu durumu ele almasını engelleyen hiçbir hüküm yoktur - ancak aşağıdaki kütüphanelerde uygulanmamıştır:

Çoklu argüman çözümlerini ihmal etmelerinin nedeninin, sırayı değiştirmeyi daha özlü hale getirmek olduğunu varsayıyorum (yani bir işlevde yalnızca bir değer döndürebileceğiniz için, kontrol akışını daha az sezgisel hale getirir) Örnek:

new Promise(function(resolve, reject) {
   return resolve(5, 4);
})
.then(function(x,y) {
   console.log(y);
   return x; //we can only return 1 value here so the next then will only have 1 argument
})
.then(function(x,y) {
    console.log(y);
});

8
Q, çok değerli çözünürlükleri desteklemez çünkü vaatler bir işlev çağrısının sonucu için vekil görevi görür, ancak uzak nesneler için vekil de olabilir. Her iki durumda da, bir dizi, bir bileşik değerin tek mantıklı temsilidir. ES6'da yıkıcı ve "yayılmış" argümanların eklenmesiyle, sözdizimi gerçekten güzelleşiyor. "Yayılma" yöntemi geçici bir noktadır.
Kris Kowal

Geri return Promise.of(x, y)aramadan gelen skaler bir değer yerine her zaman bunu yapabilirsiniz then.
Bergi

2

İşte bir CoffeeScript çözümü.

Aynı çözümü arıyordum ve bu yanıttan çok ilginç bir şey buldum: AngularJS'de birden çok argümanla ($ http gibi) vaatleri reddetmek

Bu adamın cevabı Florian

promise = deferred.promise

promise.success = (fn) ->
  promise.then (data) ->
   fn(data.payload, data.status, {additional: 42})
  return promise

promise.error = (fn) ->
  promise.then null, (err) ->
    fn(err)
  return promise

return promise 

Ve kullanmak için:

service.get().success (arg1, arg2, arg3) ->
    # => arg1 is data.payload, arg2 is data.status, arg3 is the additional object
service.get().error (err) ->
    # => err

Meli ->olmak =>?
SherylHohman

1
@SherylHohman 2015 yılında geriye dönersek , bu ES6 sözdizimi ile değil CoffeeScript ( coffeescript.org/#introduction ) ile yazılmıştır . Basit ok basit işlevlerdi ve şişman oklar ES6 ile neredeyse aynıydı (ES6 şişman okları aşağı yukarı CoffeScript'ten ödünç alındı).
Val Entin

@SherylHohman İsterseniz gönderiyi ECMA'da düzenlemekten çekinmeyin.
Val Entin

Cevabınız için teşekkürler. Sadece bunun bir kahve senaryosu çözümü olduğunu açıklığa kavuşturmak için düzenleyeceğim. Bununla birlikte, cevabınız olduğu gibi duruyor ve CoffeeScript kod tabanları için yararlı olabilir. Ancak düzenleme teklifiniz için teşekkürler: 1) Çözümünüzü düzenleme / bozma riskini alacak kadar CoffeeScript'e aşina değilim ;-). 2) Kodunuzu modern JS'ye çevirmek, "Cevabınızın orijinal amacından" bir sapma olarak görülmelidir, bu nedenle bir "düzenleme" İncelemesinden geçmemelidir. Bunun yerine, birisi kodunuzu çevirerek yeni bir Cevap gönderebilir. İdeal olarak, ilham kaynağı olarak cevabınıza geri
dönerler

0

Benjamin, Kris ve diğerleri tarafından harika bir soru ve harika bir cevap - çok teşekkürler!

Bunu bir projede kullanıyorum ve Benjamin Gruenwald'ın koduna dayalı bir modül oluşturdum . Npmjs'de mevcuttur:

npm i -S promise-spread

Sonra kodunuzda yapın

require('promise-spread');

Gibi bir kitaplık kullanıyorsanız any-promise

var Promise = require('any-promise');
require('promise-spread')(Promise);

Belki başkaları da bunu faydalı buluyor!


0

ES6'da Atamayı yeniden yapılandırmak burada yardımcı olacaktır. Örn:

let [arg1, arg2] = new Promise((resolve, reject) => {
    resolve([argument1, argument2]);
});

0

Javascript'teki fonksiyonlar herhangi bir sayıda argümanla çağrılabildiğinden ve belge onFulfilled(), aşağıdaki cümlenin yanı sıra yöntemin argümanlarına herhangi bir kısıtlama onFulfilled()getirmediğinden, promise'ın değeri olduğu sürece yönteme birden fazla argüman iletebileceğinizi düşünüyorum . ilk argüman.

2.2.2.1 Söz yerine getirildikten sonra, sözün değeri ilk argümanı olacak şekilde çağrılmalıdır.


-1

Aşağıdaki makaleden alıntı yapmak gerekirse, "" sonra "iki bağımsız değişken alır, bir başarı durumu için bir geri arama ve bir başarısızlık durumu için bir geri arama. Her ikisi de isteğe bağlıdır, böylece yalnızca başarı veya başarısızlık durumu için bir geri arama ekleyebilirsiniz."

Söz verilmiş temel sorular için genellikle bu sayfaya bakıyorum, yanılıyorsam bana haber ver

http://www.html5rocks.com/en/tutorials/es6/promises/


1
Bu yanlış, new Promisesözdizimine function(resolve, error)sahipken thensözdizimi var.then(function(arg) {
megawac

2
@megawac aslında doğru değil, sadece kötü bir şekilde ifade edildi - sonra iki (bazen 3) argüman kabul ediyor - bu oldukça nadir
Benjamin Gruenbaum 14

@BenjaminGruenbaum afaik its.then(function(/*resolve args*/){/*resolve handler*/}, function(/*reject args*/){/*reject handler*/})
megawac

2
Evet, yakından okursanız, bu cevabın iddia ettiği şey bu - bu soru bağlamında pek yararlı değil ama yanlış değil.
Benjamin Gruenbaum
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.