Promise.resolve vs new Promise (selesaikan)

98

Saya menggunakan bluebird dan saya melihat dua cara untuk menyelesaikan fungsi sinkron menjadi Promise, tetapi saya tidak mendapatkan perbedaan di antara kedua cara tersebut. Sepertinya stacktrace sedikit berbeda, jadi mereka bukan hanya sekedar alias, bukan?

Jadi cara apa yang disukai?

Cara A

function someFunction(someObject) {
  return new Promise(function(resolve) {
    someObject.resolved = true;
    resolve(someObject);
  });
}

Cara B

function someFunction(someObject) {
  someObject.resolved = true;
  return Promise.resolve(someObject);
}
Pipo
sumber
3
Promise.resolvehanyalah gula.
Qantas 94 Heavy
1
Jawaban singkat - tidak ada perbedaan dalam penggunaan. Hanya gula.
Pinal
@ Pinal Apa itu "gula"?
doubleOrt
6
@Taurus. Gula sintaksis adalah sintaks yang dirancang untuk membuat sesuatu lebih mudah dibaca atau diekspresikan. lihat: wikipedia .
Wyck

Jawaban:

85

Bertentangan dengan kedua jawaban di komentar - ada perbedaan.

Sementara

Promise.resolve(x);

pada dasarnya sama dengan

new Promise(function(r){ r(x); });

ada kehalusan.

Fungsi pengembalian janji umumnya harus memiliki jaminan bahwa fungsi tersebut tidak boleh ditampilkan secara sinkron karena mungkin ditampilkan secara asinkron. Untuk mencegah hasil yang tidak diharapkan dan kondisi balapan - lemparan biasanya diubah menjadi penolakan yang dikembalikan.

Dengan mengingat hal ini - saat spesifikasi dibuat, konstruktor promise akan aman.

Bagaimana jika someObjectyang undefined?

  • Cara A mengembalikan janji yang ditolak.
  • Cara B melempar secara serempak.

Bluebird melihat ini, dan Petka menambahkan Promise.methoduntuk mengatasi masalah ini sehingga Anda dapat terus menggunakan nilai pengembalian. Jadi cara yang benar dan termudah untuk menulis ini di Bluebird sebenarnya tidak keduanya - yaitu:

var someFunction = Promise.method(function someFunction(someObject){
    someObject.resolved = true;
    return someObject;
});

Promise.method akan mengubah lemparan menjadi penolakan dan pengembalian menjadi penyelesaian untuk Anda. Ini adalah cara yang paling aman untuk melakukan ini dan itu mengasimilasi kemampuan thenmelalui nilai-nilai kembali sehingga itu akan bekerja bahkan jika someObjectsebenarnya adalah janji itu sendiri.

Secara umum, Promise.resolvedigunakan untuk mentransmisikan objek dan janji asing (kemudian) menjadi janji. Itu kasus penggunaannya.

Benjamin Gruenbaum
sumber
"Fungsi pengembalian janji umumnya harus memiliki jaminan bahwa fungsi tersebut tidak boleh dilontarkan secara sinkron karena mungkin ditampilkan secara asinkron". Bisakah Anda menjelaskan mengapa fungsi harus sinkron atau asinkron tetapi tidak keduanya? Saat ini saya menikmati Promise.resolve (), Apakah Anda akan mengatakan bahwa menggunakan Promise.resolve()adalah anti-pola?
Ashley Coolman
2
@AshleyCoolman lihat blog.izs.me/post/59142742143/designing-apis-for-asynchrony - metode yang terkadang berperilaku asinkron harus selalu melakukannya untuk konsistensi.
Benjamin Gruenbaum
Apakah Promise.resolve()membuat contoh baru Promisedengan cara yang sama seperti menggunakan new? Jika tidak, return Promise.resolve(yourCode)akan lebih cepat dan menghindari lemparan sinkron.
Steven Vachon
1
Saya merasa tidak enak, saya menggunakan "Promise.resolve (). Then (function () {/ * case yang dapat menimbulkan kesalahan * /}). Lalu ..." untuk memastikan bahwa kesalahan tersebut menjadi janji yang ditolak ... Saya akan melihat lebih jauh ke "Promise.method"
Polopollo
1
@Polopollo atau Promise.coroutineyang lebih berguna.
Benjamin Gruenbaum
18

Ada perbedaan lain yang tidak disebutkan oleh jawaban atau komentar di atas:

Jika someObjecta Promise, new Promise(resolve)akan dikenakan biaya dua centang tambahan.


Bandingkan dua cuplikan kode berikut:

const p = new Promise(resovle => setTimeout(resovle));

new Promise(resolve => resolve(p)).then(() => {
  console.log("tick 3");
});

p.then(() => {
  console.log("tick 1");
}).then(() => {
  console.log("tick 2");
});

const p = new Promise(resovle => setTimeout(resovle));

Promise.resolve(p).then(() => {
  console.log("tick 3");
});

p.then(() => {
  console.log("tick 1");
}).then(() => {
  console.log("tick 2");
});

Potongan kedua akan mencetak 'centang 3' terlebih dahulu. Mengapa?

  • Jika nilainya adalah promise, Promise.resolve(value)akan mengembalikan nilai dengan tepat. Promise.resolve(value) === valueakan benar. lihat MDN

  • Tapi new Promise(resolve => resolve(value))akan mengembalikan janji baru yang terkunci untuk mengikuti valuejanji itu. Perlu satu centang ekstra untuk membuat 'penguncian'.

    // something like:
    addToMicroTaskQueue(() => {
      p.then(() => {
        /* resolve newly promise */
      })
        // all subsequent .then on newly promise go on from here
        .then(() => {
          console.log("tick 3");
        });
    });
    

    Telepon itu tick 1 .thenakan dijalankan lebih dulu.


Referensi:

edvard chen
sumber