2016-05-16 184 views
3

我有一組承諾,每個承諾都調用http.get()

var items = ["URL1", "URL2", "URL3"]; 
var promises = []; 
//on each URL in items array, I want to create a promise and call http.get 
items.forEach(function(el){ 
    return promises.push($http.get(el)); 
}); 
var all = $q.all(promises); 
all.then(function success(data){ 
    console.log(data); 
}).catch(function(reason){ 
    console.log("reason is", reason); 
}); 

發生的事情在我的情況

URL2.get沒有得到解決,並立即觸發了$q.allcatch()。由於此故障all.then()永遠不會被調用。

我想

我希望所有的承諾,繼續即使承諾一個被拒絕。

我找到了一個類似的post,但解決方案建議使用另一個叫做的Kris Kowal的Q。所以我想知道如何在不使用外部包的情況下實現它?

+0

見http://stackoverflow.com/questions/31424561/wait-直到所有es6承諾,完成,甚至拒絕承諾/ – guest271314

+0

@ guest271314謝謝你會看看 –

+0

我不知道爲什麼有人downvoted這個問題? –

回答

7

一個簡單的黑客可能會增加一個catch塊返回空的承諾,並從你promise.all結果過濾無效的結果,是這樣的:

let items = ["URL1", "URL2", "URL3"] 
    , promises = items.map(url => $http.get(url).catch(e => null)) 
    , all = $q.all(promises).then(data => data.filter(d => !!d)) 

all.then(data => { 
    // do something with data 
}).catch(e => { 
    // some error action 
}) 

在ES5同樣的事情:

var items = ["URL1", "URL2", "URL3"] 
    , promises = items.map(function(url){ 
    return $http.get(url).catch(function(e){return null}) 
    }) 
    , all = $q.all(promises).then(function(data){ 
    return data.filter(function(d){return !!d}) // filter out empty, null results 
    }) 

all.then(function(data){ 
    // do something with data 
}).catch(function(e){ 
    // some error action 
}) 
2

這裏是一個兼容版本.settle()的ES6,允許所有的承諾完成,然後你可以查詢每個結果,看看它是成功還是失敗:

// ES6 version of settle 
Promise.settle = function(promises) { 
    function PromiseInspection(fulfilled, val) { 
     return { 
      isFulfilled: function() { 
       return fulfilled; 
      }, isRejected: function() { 
       return !fulfilled; 
      }, isPending: function() { 
       // PromiseInspection objects created here are never pending 
       return false; 
      }, value: function() { 
       if (!fulfilled) { 
        throw new Error("Can't call .value() on a promise that is not fulfilled"); 
       } 
       return val; 
      }, reason: function() { 
       if (fulfilled) { 
        throw new Error("Can't call .reason() on a promise that is fulfilled"); 
       } 
       return val; 
      } 
     }; 
    } 

    return Promise.all(promises.map(function(p) { 
     // make sure any values or foreign promises are wrapped in a promise 
     return Promise.resolve(p).then(function(val) { 
      return new PromiseInspection(true, val); 
     }, function(err) { 
      return new PromiseInspection(false, err); 
     }); 
    })); 
} 

這可以適應用於Q庫這樣的:

// Q version of settle 
$q.settle = function(promises) { 
    function PromiseInspection(fulfilled, val) { 
     return { 
      isFulfilled: function() { 
       return fulfilled; 
      }, isRejected: function() { 
       return !fulfilled; 
      }, isPending: function() { 
       // PromiseInspection objects created here are never pending 
       return false; 
      }, value: function() { 
       if (!fulfilled) { 
        throw new Error("Can't call .value() on a promise that is not fulfilled"); 
       } 
       return val; 
      }, reason: function() { 
       if (fulfilled) { 
        throw new Error("Can't call .reason() on a promise that is fulfilled"); 
       } 
       return val; 
      } 
     }; 
    } 

    return $q.all(promises.map(function(p) { 
     // make sure any values or foreign promises are wrapped in a promise 
     return $q(p).then(function(val) { 
      return new PromiseInspection(true, val); 
     }, function(err) { 
      return new PromiseInspection(false, err); 
     }); 
    })); 
} 

使用與您的特定代碼:

var items = ["URL1", "URL2", "URL3"]; 
$q.settle(items.map(function(url) { 
    return $http.get(url); 
})).then(function(data){ 
    data.forEach(function(item) { 
     if (item.isFulfilled()) { 
      console.log("success: ", item.value()); 
     } else { 
      console.log("fail: ", item.reason()); 
     } 
    }); 
}); 

注:.settle()返回一個承諾,始終解析,從不拒絕。這是因爲無論您通過多少承諾都拒絕,它仍然可以解決,但會返回您通過承諾的信息可以解決或拒絕。

0

我裹在$ Q $的資源,只有解決狀態

var promises = [ 
    $q(function (resolve) { 
     Me.get({params: 12}).$promise.then(function (data) { 
      resolve(data); 
     }, function (err) { 
      resolve(err); 
     }); 
    }), 
    $q(function (resolve) { 
     Me.get({params: 123}).$promise.then(function (data) { 
      resolve(data); 
     }, function (err) { 
      resolve(err); 
     }); 
    }), 
    $q(function (resolve) { 
     Me.get({params: 124}).$promise.then(function (data) { 
      resolve(data); 
     }, function (err) { 
      resolve(err); 
     }); 
    })]; 

,然後使用$ q.all諾言