在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/HTML/ 多次請求因為網(wǎng)絡(luò)無法保證響應(yīng)順序,如何保證獲得所有響應(yīng)結(jié)果后生成的列表結(jié)果的順序

多次請求因為網(wǎng)絡(luò)無法保證響應(yīng)順序,如何保證獲得所有響應(yīng)結(jié)果后生成的列表結(jié)果的順序與請求順序一致?

看很多人都誤會成了一次性發(fā)送10次,補充為這樣:

假如用戶可以連續(xù)點擊按鈕,每次發(fā)1次請求,每次獲得響應(yīng)結(jié)果后會生成一個li,因為網(wǎng)絡(luò)狀態(tài)的影響后發(fā)出的請求可能先響應(yīng),假如點了10次,如何保證10個li的順序與請求的順序一致!

使用Promise.all的答案肯定都是不對的,因為你無法預(yù)測用戶點擊按鈕的時機,用戶可能一兩秒完成10次點擊,但也可能在10秒內(nèi)完成......肯定不能說我等用戶點完10次再使用Promise.all請求,何況實際情況不一定是10次。
這是我一次面試唯一沒答的很好的題目,所以印象比較深刻,我開始也答的Promise.all,被直接否定,后面我提到在請求報文中攜帶相關(guān)參數(shù),響應(yīng)中返回,本地做mapping關(guān)系來實現(xiàn),但面試官依然不是很滿意。后面經(jīng)我詢問后面試官只提到了思路,說了幾個詞記得不是很清楚,后續(xù)查資料猜測貌似是在請求響應(yīng)包含一個Request-Id字段,并使用 UUID 作為該值......沒實踐過不敢確定!

回答
編輯回答
黑與白

Promise.all可以保證順序但是得等到所有請求完畢才會觸發(fā)

function p1(time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(time);
        }, time);
    })
}

Promise.all([p1(5000), p1(1000)]).then(function (res) {
    console.log(res);//[5000,1000]
});
2018年2月14日 06:14
編輯回答
孤客

es6的async函數(shù)可以解決這個問題,異步函數(shù)一旦遇到await就會先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。
http://es6.ruanyifeng.com/#do...

2018年9月17日 09:55
編輯回答
墻頭草

一,可以把請求回來的數(shù)據(jù)做一個標(biāo)識,然后把所有數(shù)據(jù) 都放到一個數(shù)組中,按標(biāo)識 排序。
二,使用Promise.all,接收的是一個數(shù)組,等到數(shù)組中的請求全部完成,就執(zhí)行Promise.all().then(values => {}),其中values就是一個數(shù)組,且排好序的

2017年3月3日 18:23
編輯回答
北城荒

萬無一失的方法是:
從第一個開始執(zhí)行,等第一個執(zhí)行結(jié)束后,再執(zhí)行第二個,依次類推。
這種同步方法效率太低。
那么可以考慮Promise.all呢?
擔(dān)心promise.all中的所有task都是異步執(zhí)行的?
那么真正返回結(jié)果是依task列表順序返回,所以就它了。

2017年11月13日 11:00
編輯回答
任她鬧

不知道你說的是不是X-Request-ID,如果是,那我也不清楚怎么用這個header來區(qū)分不同的請求,除非是服務(wù)端配合。

我所想到的方法是使用一個自增的閉包變量來區(qū)分每個AJAX請求,這一點樓上很多人都想到了。

接下來,是如何在請求返回之后根據(jù)這個閉包變量的值在適當(dāng)?shù)奈恢貌迦?code><li>元素,以保證插入后的順序與點擊順序相同(而不是與請求返回的順序相同)。

我的方案是在請求的時候就append一個<li>元素,并設(shè)置為隱藏,同時給這個元素設(shè)置一個data,值為閉包變量的值。

當(dāng)請求返回之后,根據(jù)閉包變量找到對應(yīng)的<li>元素,插入內(nèi)容后將其顯示出來即可。類似于下面這樣:

var idx = 0;

$(btn).on("click", function() {
    let i = idx++;
    $(...).append('<li class="hide" data-idx="`${i}`"></li>');
    $.ajax({
        ...
        success: function(resp) {
            var li = $("li[data-idx='`${i}`']");
            ...
        };
    });
});
2018年9月1日 06:30
編輯回答
柚稚

以下代碼實現(xiàn)了:

  • 并發(fā)請求
  • 順序操作
  • 不需要等待全部請求完畢
  • 可以直接運行
(()=>{
    Promise.allInOrder = (promises, thenForEach)=>{
        let sequence = Promise.resolve();
        
        promises.forEach(function(request){
            sequence = sequence.then(function(){
              return request.then(thenForEach);
          });
        });

    };
})();

// test
(()=>{
    let timeConsumingFunc = param=>new Promise(
            (resolve)=>{
                let timeout = Math.random() * 5000;
                console.log(`task ${param} will be resolved in ${timeout}ms`);
                setTimeout(()=>{
                    console.log(`${param} resolved`);
                    resolve(param+10);
                }, timeout);
            }
        );
    Promise
        .allInOrder(
            [timeConsumingFunc(1), timeConsumingFunc(2), timeConsumingFunc(3)],
            d=>{
                return new Promise(function(resolve) {
                  console.log(d);
                resolve();
              });
            }
        )
})();

這是我以前的一個提問的最終解決方法,也可以采用我采納的哪個答案,只是代碼會臃腫一些

補充:
針對你說的情況,可以間隔1s內(nèi)的鼠標(biāo)點擊作為一組請求用上面方法并發(fā)請求,間隔大于1s的同步繼發(fā)操作

2017年9月14日 18:41
編輯回答
真難過

其實如果后天和前臺能夠聯(lián)動,最好是請求時有一個標(biāo)號,然后返回時帶標(biāo)號,這樣肯定沒有問題,且無論多少返回都可以先展示,后期再依序調(diào)整。
其實如果更友好的,發(fā)一次請求,就在數(shù)組中填一個展位符信息,接收到一個就更新數(shù)組,并刷新展示。

2017年3月10日 04:07
編輯回答
妖妖

在請求的時候帶過去要顯示的li的順序;然后響應(yīng)回來順序;按順序排列吧

2018年6月6日 19:58
編輯回答
巴扎嘿

在請求里帶一個時間戳參數(shù),然后再原封不動把這個時間戳返回來,并根據(jù)時間進行排序。

2018年4月21日 13:36
編輯回答
未命名

如果不是面試中,是實際項目中碰到類似問題,而且必須要保證返回順續(xù)的話,因為有的時候第二次請求需要第一次的結(jié)果,我會采用當(dāng)用戶單擊按鈕以后,在請求沒有回來之前,按鈕變?yōu)榻脿顟B(tài),只有成功返回了,才可以進行下一次請求,原因是你永遠無法預(yù)測用戶是貓還是狗,所以最好的辦法就是不讓用戶有連續(xù)點擊的機會

2017年8月5日 02:29