为了账号安全,请及时绑定邮箱和手机立即绑定

关于js promise队列的疑问

关于js promise队列的疑问

人到中年有点甜 2019-03-20 18:15:26
学习promise的过程中遇到一个关于队列的问题,在开发中遇到一个问题,需要循环请求上传的接口,但是下面的的方法好像没有做到队列,跪求大神帮我改造需求是执行完一个再执行一个,直到最后一个,串行,对列的概念也不是很懂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);});
查看完整描述

6 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

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

查看完整回答
反对 回复 2019-04-02
?
互换的青春

TA贡献1797条经验 获得超6个赞

问题是,这不是队列,而是foreach执行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);

});


查看完整回答
反对 回复 2019-04-02
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

不知道,你是不是要达到 串行上传还是并行上传的目的 ?


// 下面是串行上传的

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)

})


查看完整回答
反对 回复 2019-04-02
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

楼主我来对你的代码做点注释,你自己再看看问题出在哪里


// 定义一个队列构造器

function queue(files) {


  // 使用Promise.resolve(val)生成一个Promise实例promise

  // promise的状态已转换为Resolved状态,

  // 这时promise仍可通过then方法获取到Resolved的结果val(这里的val为空,所以是undefined)

  let promise = Promise.resolve(); 

  

  // 遍历一次传入的数组

  files.forEach(file => {


    // promise对象添加then方法,并将then方法的返回值重新赋值给promise并传入resolve回调,

    // 因为只传了一个函数(这个函数没有参数,所以没法捕获上一次操作完成返回的值,

    // 事实上,楼主也没有在每次完成返回值,因为resolve()中没有给值。)参数,

    // 所以reject的回调为undefined

    promise = promise.then(() => { 


    // then.resolve回调中返回了一个新的Promise实例,新的实例通过构造的方式生成,

    // 构造传入了"resolve"这样一个名字的函数参数,作为promise的resolve回调,没有reject

      return new Promise(resolve => { 


         // 新构造的Promise实例的resolve回调中执行异步上传方法

         doThing(file, () => { 

             

             //上传操作,访问接口


             // 上传完成resolve这个promise,但是没有给下一个操作传入值,

             // 所以最后调用的data为空

             resolve();

           });

      });

    });

  });

  // 返回了新的promise引用,事实上,这个promise引用就已经是个队列了

  return promise;

}


// 这一步调用之后,做了什么事情?从这里再看这个queue内部的执行过程,

// 调用之后,第一个上传文件的操作就会立即启动,上传完成之后就会继续上传下一个,

// 直到这数组中都传完, 最后一个操作的resolve被下面这个then捕获

queue([file1, file2, file3]) 


//获取了最后一个promise实例成功后resolve的值

.then(data => { 


  // 打印resolve的值

  console.log(data); 

});

查看完整回答
反对 回复 2019-04-02
?
四季花海

TA贡献1811条经验 获得超5个赞

你队列的做法没问题,只是最后没有返回 data 而已。如果你需要 data 的话,可以在 resolve() 里返回。

查看完整回答
反对 回复 2019-04-02
  • 6 回答
  • 0 关注
  • 617 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号