回答編集履歴

1 修正&追記

karamarimo

karamarimo score 2388

2018/11/28 12:15  投稿

まずJavaScriptの非同期処理とイベントループについて調べて理解されることをおすすめします。
非同期に呼び出される関数は、少なくとも現在のコールスタックが空になるまで呼び出されることはありません。今の場合、`T.get()`のコールバック(`(err, data, response) => {...}`の部分)は3回設定されるわけですが、これらは少なくとも`for`文が終わったあと、任意の順番で実行されます。
非同期に呼び出される関数は、少なくとも現在のコールスタックが空になるまで呼び出されることはありません。今の場合、`T.get()`のコールバック(`(err, data, response) => {...}`の部分)は3回設定されるわけですが、これらは少なくとも`for`文が終わったあと、任意の順番で実行されます。検索結果が3回とも同じになるのも、`for`文内で`lastId`は`''`のままなので`params`の更新ができていないことが原因です。
追記のコードでは、`resolve`する場所が間違っています。コールバックが呼び出された時点で完了したとみなしたいので、コールバックの中で`resolve`しないと意味がありません。
ですが、[twit](https://www.npmjs.com/package/twit)のUsageを見る限り Promise をサポートしているので自分でPromiseを作る必要がそもそもありません。
> 検索結果(3回とも同じ結果)が出てきます。
これは別の原因です。
テストしてないですが、以下のコードのようにできると思います。
```js
let params = {
   q: '#ハッシュタグ since:2018-11-28_00:00:00_JST until:2018-11-28_00:30:00_JST',
   count: 3,
   max_id: lastId,
   result_type: 'recent',
   include_entities: false
}
!(async () => {
 for (let i = 0; i < 3; i++) {
   params.max_id = lastId
   const result = await T.get('search/tweets', params)
   result.data.statuses.forEach(function (val, index, ar) {
     console.log(index);
     console.log('@' + val.user.screen_name);
     console.log(val.text);
     lastId = val.id.str
   })
 }
})()
```
と`params`はなっているので、`max_id` property の値はこの時点での`lastId`の評価された値`''`になります。このあと`lastId`の値を変えても意味はありません。  
 
そのため、`params`の値を自分で変えるなどする必要があります。  
---
イベントループの分かりやすい動画(英語)
[Jake Archibald: In The Loop - JSConf.Asia 2018 (YouTube)](https://youtu.be/cCOL7MC4Pl0)

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る