2016-12-11 18 views
8

Tôi đang cố gắng để chuỗi hứa hẹn để chuỗi sẽ phá vỡ nếu một lời hứa bị từ chối. Tôi theo sau sự dẫn dắt của một số previous SO question và cố gắng áp dụng nó cho những lời hứa gốc, nhưng tôi nghĩ rằng tôi hiểu lầm cách mọi thứ hoạt động.Phá vỡ chuỗi lời hứa javascript một cách rõ ràng

Dưới đây là cách tôi đã viết lại đoạn code:

Promise.resolve() 
    .then(function() { 
     return step(1) 
      .then(null, function() { 
       stepError(1); 
      }); 
    }) 
    .then(function() { 
     return step(2) 
      .then(null, function() { 
       stepError(2); 
      }); 
    }) 
    .then(function() { 
     return step(3) 
      .then(null, function() { 
       stepError(3); 
      }); 
    }); 

function step(n) { 
    console.log('Step '+n); 
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n); 
} 

function stepError(n) { 
    console.log('Error '+n); 
    return Promise.reject(n); 
} 

Sản lượng của các mã trên là:

Step 1 
Step 2 
Error 2 
Step 3 
[UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 2] 

Trong hiểu biết của tôi, bước 2 nên phá vỡ các chuỗi và bước 3 không nên được thực thi. Khi bước (2) trả về một lời hứa bị từ chối, bướcError (2) được thực hiện như mong đợi. Nhưng vì nó trả về Promise.reject (2), chức năng trong kế tiếp không nên được thực hiện, và vì không bắt kịp, lời hứa từ chối bước 2 dường như - như mong đợi - được chuyển tiếp cho đến khi nó thoát khỏi bởi vì nó không tìm thấy bất kỳ trình xử lý nào.

Tôi thiếu gì ở đây?

Đây là một JSFiddle để chơi với: https://jsfiddle.net/6p4t9xyk/

Trả lời

10

Trong hiểu biết của tôi, bước 2 nên phá vỡ các chuỗi ...

sẽ, nhưng bạn đã vô tình chuyển đổi mà từ chối thành một giải pháp.

Điều quan trọng về lời hứa là mỗi cuộc gọi đến then tạo ra một mới lời hứa đó đã được giải quyết/từ chối dựa trên những gì các then callback (s) làm, và gọi lại xử lý một sự từ chối chuyển đổi mà từ chối vào độ phân giải trừ nó có ý định khác.

Vì vậy, ở đây:

return step(2) 
    .then(null, function() { // This handler converts the 
     stepError(2);   // rejection into a resolution 
    });      // with the value `undefined` 

Đó là để bạn có thể có xử lý lỗi mà bù đắp cho lỗi.

Kể từ stepError trả về một từ chối, bạn có thể tiếp tục từ chối bởi chỉ cần thêm một return:

return step(2) 
    .then(null, function() { 
     return stepError(2); // Added `return` 
    }); 

... hoặc xen kẽ, loại bỏ hoàn toàn xử lý:

return step(2); 

... hoặc bạn có thể throw trong cuộc gọi lại, tự động bị từ chối.

Cảnh báo từ chối không được giải quyết là do thực tế không có gì tiêu thụ từ chối từ stepError.


Dưới đây là một ví dụ trả lại kết quả của stepError:

Promise.resolve() 
 
    .then(function() { 
 
     return step(1) 
 
      .then(null, function() { 
 
       return stepError(1); // Added `return` 
 
      }); 
 
    }) 
 
    .then(function() { 
 
     return step(2) 
 
      .then(null, function() { 
 
       return stepError(2); // Added `return` 
 
      }); 
 
    }) 
 
    .then(function() { 
 
     return step(3) 
 
      .then(null, function() { 
 
       return stepError(3); // Added `return` 
 
      }); 
 
    }); 
 

 
function step(n) { 
 
    console.log('Step '+n); 
 
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n); 
 
} 
 

 
function stepError(n) { 
 
    console.log('Error '+n); 
 
    return Promise.reject(n); 
 
}

0

Như @TJCrowder nói, bạn quên return kết quả của xử lý lỗi (hoặc throw từ nó). Để khắc phục điều đó, tôi muốn khuyên bạn nên làm một trong hai

function withStepError(n, promise) { 
    return promise.catch(function(err) { 
     console.log('Error '+err+' from '+n); 
     throw new Error("failed at "+n); 
    }); 
} 
Promise.resolve() 
.then(function() { 
    return withStepError(1, step(1)); 
}) 
.then(function() { 
    return withStepError(2, step(2)); 
}) 
.then(function() { 
    return withStepError(3, step(3)); 
}); 

hoặc

function getStepError(n) { 
    return function(err) { 
     console.log('Error '+err+' from '+n); 
     throw new Error("failed at "+n); 
    }; 
} 

Promise.resolve() 
.then(function() { 
    return step(1).catch(getStepError(1)); 
}) 
.then(function() { 
    return step(2).catch(getStepError(2)); 
}) 
.then(function() { 
    return step(3).catch(getStepError(3)); 
}); 
Các vấn đề liên quan