Promise.resolve so với Promise mới (giải quyết)


93

Tôi đang sử dụng bluebird và tôi thấy có hai cách để giải quyết các hàm đồng bộ thành một Promise, nhưng tôi không nhận được sự khác biệt giữa cả hai cách. Có vẻ như stacktrace hơi khác một chút, vì vậy chúng không chỉ là một alias, phải không?

Vậy cách ưu tiên là gì?

Cách A

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

Cách B

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

3
Promise.resolvechỉ là đường.
Qantas 94 Heavy

1
Câu trả lời ngắn gọn - không khác biệt về cách sử dụng. Chỉ là đường.
Pinal

@Pinal "Đường" là gì?
doubleOrt

5
@Chòm sao Kim Ngưu. Cú pháp đường là cú pháp được thiết kế để làm cho mọi thứ dễ đọc hoặc dễ diễn đạt hơn. xem: wikipedia .
Wyck

Câu trả lời:


82

Trái ngược với cả hai câu trả lời trong các bình luận - có sự khác biệt.

Trong khi

Promise.resolve(x);

về cơ bản giống như

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

có một sự tinh tế.

Các hàm trả về Promise thường phải có sự đảm bảo rằng chúng không được ném đồng bộ vì chúng có thể ném không đồng bộ. Để ngăn chặn các kết quả không mong muốn và các điều kiện của cuộc đua - các cú ném thường được chuyển đổi thành các lần từ chối trả về.

Với điều này trong tâm trí - khi thông số kỹ thuật được tạo, hàm tạo hứa sẽ được ném an toàn.

Nếu someObjectundefinedgì?

  • Cách A trả lại một lời hứa bị từ chối.
  • Cách B ném đồng bộ.

Bluebird đã thấy điều này và Petka đã thêm Promise.methodđể giải quyết vấn đề này để bạn có thể tiếp tục sử dụng các giá trị trả về. Vì vậy, cách chính xác và dễ dàng nhất để viết điều này trong Bluebird thực sự không phải - đó là:

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

Promise.method sẽ chuyển đổi các lần ném thành từ chối và quay lại giải quyết cho bạn. Đây là cách an toàn nhất để làm điều này và nó đồng hóathen ables thông qua các giá trị trả về để nó hoạt động ngay cả khi someObjectthực tế là một lời hứa.

Nói chung, Promise.resolveđược sử dụng để đúc các đối tượng và các lời hứa ngoại (thenables) cho các lời hứa. Đó là trường hợp sử dụng của nó.


"Các hàm trả về Promise thường phải đảm bảo rằng chúng không được ném đồng bộ vì chúng có thể ném không đồng bộ". Bạn có thể mở rộng về lý do tại sao các hàm phải đồng bộ hoặc không đồng bộ nhưng không phải cả hai? Hiện tại tôi thích Promise.resolve (), Bạn có muốn nói rằng việc sử dụng Promise.resolve()là anti-pattern không?
Ashley Coolman

2
@AshleyCoolman xem blog.izs.me/post/59142742143/designs-apis-for-asynchrony - một phương thức đôi khi hoạt động không đồng bộ nên luôn làm như vậy để có tính nhất quán.
Benjamin Gruenbaum

Promise.resolve()tạo một phiên bản mới Promisegiống như cách sử dụng newkhông? Nếu không, return Promise.resolve(yourCode)sẽ nhanh hơn và tránh ném đồng bộ.
Steven Vachon

1
Tôi cảm thấy không ổn, tôi sử dụng trường hợp "Promise.resolve (). Then (function () {/ * có thể tạo ra lỗi * /}). Then ..." để chắc chắn rằng lỗi đó trở thành một lời hứa bị từ chối ... Tôi sẽ xem xét kỹ hơn về "Promise.method"
Polopollo.

1
@Polopollo hoặc Promise.coroutinecái nào hữu ích hơn.
Benjamin Gruenbaum

16

Có một sự khác biệt khác không được đề cập trong các câu trả lời hoặc nhận xét ở trên:

Nếu someObjectlà một Promise, new Promise(resolve)sẽ tốn thêm hai lần đánh dấu.


So sánh hai đoạn mã sau:

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

Đoạn mã thứ hai sẽ in 'đánh dấu 3' trước tiên. Tại sao?

  • Nếu giá trị là một lời hứa, Promise.resolve(value)sẽ trả về giá trị chính xác. Promise.resolve(value) === valuesẽ là sự thật. xem MDN

  • Nhưng new Promise(resolve => resolve(value))sẽ trả lại một lời hứa mới đã bị khóa để làm theo valuelời hứa. Nó cần thêm một lần đánh dấu để thực hiện 'khóa trong'.

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

    Cuộc tick 1 .thengọi sẽ chạy trước.


Người giới thiệu:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.