鍍金池/ 問答/HTML/ 關于js promise隊列的疑問

關于js promise隊列的疑問

學習promise的過程中遇到一個關于隊列的問題,在開發(fā)中遇到一個問題,需要循環(huán)請求上傳的接口,但是下面的的方法好像沒有做到隊列,跪求大神幫我改造

需求是執(zhí)行完一個再執(zhí)行一個,直到最后一個,串行,對列的概念也不是很懂

function queue(files) {
  let promise = Promise.resolve();
  files.forEach(file => {
    promise = promise.then(() => {
      return new Promise(resolve => {
         doThing(file, () => {
           //上傳操作,訪問接口
             resolve();
           });
      });
    });
  });
  return promise;
}

queue([file1, file2, file3]).then(data => {
  console.log(data);
});
回答
編輯回答
網(wǎng)妓

一個promise的resolve只能使用一次,第二次以后的使用都是無效的
你需要RxJs

2017年8月23日 07:17
編輯回答
擱淺

不知道,你是不是要達到 串行上傳還是并行上傳的目的 ?

// 下面是串行上傳的
function queue(arr, handle) {
let index = 0
let length = arr.length

return new Promise((resolve, reject) => {

!(function next() {
  try {
    handle(arr[index])
      .then(function () {
        ++index < length
          ? next()
          : resolve()
      })
      .catch(reject)
  } catch (err) {
    reject(err)
  }
})()

})
}

function upload(file) {
return new Promise((resolve, reject) => {

// 上傳文件
setTimeout(function () {
  console.log(`upload ${file}`)
  resolve()
}, file * 1000 )

})
}

queue(['3', '2', '1'], upload).then(data => {
console.log('ok');
}).catch(err => {
console.log('error', err)
})

2017年1月17日 03:55
編輯回答
青檸

樓主我來對你的代碼做點注釋,你自己再看看問題出在哪里

// 定義一個隊列構造器
function queue(files) {

  // 使用Promise.resolve(val)生成一個Promise實例promise
  // promise的狀態(tài)已轉換為Resolved狀態(tài),
  // 這時promise仍可通過then方法獲取到Resolved的結果val(這里的val為空,所以是undefined)
  let promise = Promise.resolve(); 
  
  // 遍歷一次傳入的數(shù)組
  files.forEach(file => {

    // promise對象添加then方法,并將then方法的返回值重新賦值給promise并傳入resolve回調,
    // 因為只傳了一個函數(shù)(這個函數(shù)沒有參數(shù),所以沒法捕獲上一次操作完成返回的值,
    // 事實上,樓主也沒有在每次完成返回值,因為resolve()中沒有給值。)參數(shù),
    // 所以reject的回調為undefined
    promise = promise.then(() => { 

    // then.resolve回調中返回了一個新的Promise實例,新的實例通過構造的方式生成,
    // 構造傳入了"resolve"這樣一個名字的函數(shù)參數(shù),作為promise的resolve回調,沒有reject
      return new Promise(resolve => { 

         // 新構造的Promise實例的resolve回調中執(zhí)行異步上傳方法
         doThing(file, () => { 
             
             //上傳操作,訪問接口

             // 上傳完成resolve這個promise,但是沒有給下一個操作傳入值,
             // 所以最后調用的data為空
             resolve();
           });
      });
    });
  });
  // 返回了新的promise引用,事實上,這個promise引用就已經是個隊列了
  return promise;
}

// 這一步調用之后,做了什么事情?從這里再看這個queue內部的執(zhí)行過程,
// 調用之后,第一個上傳文件的操作就會立即啟動,上傳完成之后就會繼續(xù)上傳下一個,
// 直到這數(shù)組中都傳完, 最后一個操作的resolve被下面這個then捕獲
queue([file1, file2, file3]) 

//獲取了最后一個promise實例成功后resolve的值
.then(data => { 

  // 打印resolve的值
  console.log(data); 
});

另外,我這里還有個學習promise做的筆記,你可以回顧下
我的Promise筆記

2017年5月18日 11:43
編輯回答
怪痞

問題是,這不是隊列,而是foreach執(zhí)行promise,遞歸一下就好了。

function doThing(file) {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('doThing', file)
      resolve('result:' + file)
    }, 500)
  })
}

function queue(files, data = []) {
  return new Promise((resolve) => {
    if (files.length > 0) {
      let file = files.shift();
      doThing(file).then((res) => {
        data.push(res)
        resolve(queue(files, data))
      })
    } else {
      resolve(data)
    }
  })
}

queue(['file1', 'file2', 'file3']).then(data => {
  console.log(data);
});
2017年8月7日 07:56
編輯回答
朕略萌

題主你隊列的做法沒問題,只是最后沒有返回 data 而已。如果你需要 data 的話,可以在 resolve() 里返回。

另外自薦一下我的講堂:Promise 的 N 種用法,里面除了詳細介紹了 Promise 的各種用法,還專門寫了兩種隊列的處理。

2018年6月26日 22:46
編輯回答
陪我終

麻煩問一下,你要做什么?是按照隊列去走還是怎么的?

貼一個 jsfiddle ,是按照隊列執(zhí)行的

https://jsfiddle.net/weisiwu/...

2017年3月7日 19:03