關於nextTick的一點問題

最近幾天在拿node搞graphql,用了dataloader來解決n+1問題。寫loader的時候把loader放到了全局,當時內心就煩嘀咕,要是兩個請求一塊兒打過來,dataloader返回的數據會不會混淆? 好比如下這種狀況:node

const pageLoader = new DataLoader(async (ids: string[]) => {
       return controller.getPages(ids);
    });
複製代碼

假如兩個請求的id有重合,一個ids=[1,2], 另一個ids=[2,3],若是dataloader把ids合併成[1,2,3]去請求,那返回的結果咋辦?git

搞數據試了幾回,發現dataloader會在第一個請求完成以後再去load第二個請求,並不存在我上面腦補的狀況。 那問題又來了,dataloader咋搞的?github

DataLoader

翻了下dataloader的源碼,在調用loader.load(id)的時候,會作兩件事:promise

  1. 生成一個promise,合着id一塊兒放到queue裏。
  2. 若是是第一個key,那還要啓一個任務來收集queue裏的id
this._queue.push({ key, resolve, reject });
      // Determine if a dispatch of this queue should be scheduled.
      // A single dispatch should be scheduled per queue at the time when the
      // queue changes from "empty" to "full".
      if (this._queue.length === 1) {
        if (shouldBatch) {
          // If batching, schedule a task to dispatch the queue.
          enqueuePostPromiseJob(() => dispatchQueue(this));
        } else {
          // Otherwise dispatch the (queue of one) immediately.
          dispatchQueue(this);
        }
      }
      
var enqueuePostPromiseJob =
  typeof process === 'object' && typeof process.nextTick === 'function' ?
    function (fn) {
      if (!resolvedPromise) {
        resolvedPromise = Promise.resolve();
      }
      resolvedPromise.then(() => process.nextTick(fn));  // 關鍵, 任務被放到nextTick來執行了
    } :
    setImmediate || setTimeout;
複製代碼

能夠看到,收集queue裏id的任務被放到nextTick裏面來執行了。 也就是說,在nextTick回調執行以前load的id會被放到queue裏做爲一個id集合來處理,而node在處理下一個請求以前,就調用了nextTick的回調。因此 兩個請求的id是不會混合的。。瀏覽器

但問題又來了,兩個request的回調函數應當是放在事件循環的Poll Phase裏面的,在處理完這個phase的隊列以前,nextTick爲何會被調用?bash

nextTick

翻了n多篇文章,大概講的都是node維護了一個nextTickQueue,libuv在每一個phase即將結束,要進入下個phase以前,會檢查nextTickQueue裏的回調並執行。async

而後看到了這篇文章,講node 11.0以後, 爲了和瀏覽器一致,在macrotask執行完以後都會去執行microtask。 這個理論說得通,但問題是我用的是node 8,因此應該不是由於這個緣由。ide

最後去提了一個issue,大神給的解答大概就是說nexttick和eventloop壓根兒不搭嘎,eventloop每次跑完一個handler都會跑nexttick。 大概就這樣吧,也不想深究了,畢竟node 11之後,感受已經徹底能夠把nexttick看成一個microtask來看了。函數

參考文獻

You really hate NodeJS! Here’s why…oop

相關文章
相關標籤/搜索